kotlin - 装箱可为空整数的奇怪行为

标签 kotlin nullable

我在 Kotlin 中遇到可为 null 变量的问题 我在 Kotlin 文档中找到了这个示例:

val a: Int = 100
val boxedA: Int? = a
val anotherBoxedA: Int? = a

val b: Int = 10000
val boxedB: Int? = b
val anotherBoxedB: Int? = b

println(boxedA === anotherBoxedA) // true
println(boxedB === anotherBoxedB) // false

输出

true
false

他们解释说这是 JVM 应用于 -128 到 127 之间的 Integer 的内存优化。它不适用于 b 引用,因此它们是不同的对象。

然后我将 a 和 b 转换为可空

val a: Int? = 100
val boxedA: Int? = a
val anotherBoxedA: Int? = a

val b: Int? = 10000
val boxedB: Int? = b
val anotherBoxedB: Int? = b

println(boxedA === anotherBoxedA) // true
println(boxedB === anotherBoxedB) // true

输出

true
true

是什么造成了这种差异?谁能给我解释一下吗?

最佳答案

在第一种情况(不可为空)中,装箱发生在所有这些行上,正如您已正确识别的那样:

val boxedA: Int? = a
val anotherBoxedA: Int? = a

val boxedB: Int? = b
val anotherBoxedB: Int? = b

这是因为 Int? 在 Java 中通常翻译为 java.lang.Integer

因此,在最后两行创建了 2 个新的、不同的 java.lang.Integer 实例,因为 b 大于 127。

但是,在第二种可为空的情况下,装箱仅发生在这些行上:

val a: Int? = 100

val b: Int? = 10000

请注意,由于 ab 可为空,因此它们现在是包装类型 java.lang.Integer。它们已经装箱了!因此,当您将它们分配给 boxedAboxedBanotherBoxedAanotherBoxedB 时,不会发生装箱,也不会产生新实例创建了 java.lang.Integer 。您只需将一个 Integer 类型的变量分配给另一个 Integer 类型的变量。

因此,只有一个 java.lang.Integer 实例存储 10000,并且是在 val b: Int? 行创建的。 = 10000

如果您将 Kotlin 翻译为 Java 可能会有所帮助:

Integer b = 10000; // boxing only occurs here
Integer boxedB = b;
Integer anotherBoxedB = b;

关于kotlin - 装箱可为空整数的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69415755/

相关文章:

android - 如何创建用于测试的对象的 PagedList?

c# - Nullable<T> 的装箱/拆箱行为如何可能?

Java8 中 Optional::map 的 Kotlin 等价物

java - 在Kotlin/Java中将列表过滤到特定大小

c# - 泛型参数的可空返回值

c# - 给字符串一个空值

Android View 绑定(bind) - 多模块项目中 Unresolved 引用

java - 无法从 java 调用 Kotlin 的扩展属性

android - Kotlin Gradle 依赖项中的 "implementation"是什么?