[通过一个简单的通用接口进行实验,我发现Kotlin似乎总是使用Java原语来支持不可为空的变量,并且只将其放入getter中。 (使用IDEA的反编译功能)。如果创建的属性不是基于满足通用属性的,则没有装箱。所以这段代码:
interface Provider<T: Any> {
val value: T
}
class WrappedInt(override val value: Int): Provider<Int>{
val primitiveValue = value
}
基本编译为该Java代码:
public final class WrappedInt implements Provider {
private final int value;
private final int primitiveValue;
public WrappedInt(int value) {
this.value = value;
this.primitiveValue = this.getValue();
}
@NotNull
public Integer getValue() {
return this.value;
}
public final int getPrimitiveValue() {
return this.primitiveValue;
}
}
我想知道的是,提供属性的原始副本是否会有任何价值,所以当通用接口无关紧要时,将有一个优化的吸气剂可用。还是VM足够聪明,可以跳过将直接变成原始变量或方程式的变量装箱?例如:
val variable = WrappedInt(5)
val result = variable.value * 5 // Did the backing field get boxed and immediately unboxed here?
我主要对Android的ART感兴趣,但也对JVM感兴趣。
注意,如果确实提供原始属性是有帮助的,则最好在类定义中交换两个属性,并为接口属性使用已定义的getter,这样就只有一个备用字段。我仅以这种方式保留了它,以说明无论getter返回盒装值如何,后备字段都是原始类型。
自动装箱发生在编译时,而不是运行时。字节码:
val x = WrappedInt(5)
val y = x.value * 5
val z = x.primitiveValue * 5
显示y
而不是z
的方程式发生自动拆箱。因此,如果接口实现可能经常访问其备用值,则提供备用原始getter可能会有一些好处。