admin管理员组

文章数量:1122846

The String interning works as I expected but I can't find out how it works for other types.

For example, for Integers in Java:

class Main {
    public static void main(String[] args) {
        Integer x = 127;
        Integer y = 127;
        System.out.println(x == y); // true
        
        Integer xx = 128;
        Integer yy = 128;
        System.out.println(xx == yy); // false
    }
}
fun main() {
    val x: Int = 127
    val y: Int = 127
    println(x === y) // true
    
    val xx: Int = 128
    val yy: Int = 128
    println(xx === yy) // true
    
    val xxx: Int = 128128128
    val yyy: Int = 128128128
    println(xxx === yyy) // true
}

But in Kotlin it always returns true. Why is that? I just want to read a little bit about this but don't know where to find any info.

Edit:

Thank you guys!


fun main() {
    val a: Int? = 128
    val b: Int? = 128
    
    println(a === b) // false
    println(a == b) // true
    
    val aa: Int? = 127
    val bb: Int? = 127
    
    println(aa === bb) // true
    println(aa == bb) // true
}
  • Non-nullable numerical types (e.g., Int, Double):
    • Represented as primitives on the JVM.
    • === and == comparisons are equivalent (compare values, not references).
  • Nullable numerical types (e.g., Int?, Double?):
    • Boxed on the JVM.

The String interning works as I expected but I can't find out how it works for other types.

For example, for Integers in Java:

class Main {
    public static void main(String[] args) {
        Integer x = 127;
        Integer y = 127;
        System.out.println(x == y); // true
        
        Integer xx = 128;
        Integer yy = 128;
        System.out.println(xx == yy); // false
    }
}
fun main() {
    val x: Int = 127
    val y: Int = 127
    println(x === y) // true
    
    val xx: Int = 128
    val yy: Int = 128
    println(xx === yy) // true
    
    val xxx: Int = 128128128
    val yyy: Int = 128128128
    println(xxx === yyy) // true
}

But in Kotlin it always returns true. Why is that? I just want to read a little bit about this but don't know where to find any info.

Edit:

Thank you guys!


fun main() {
    val a: Int? = 128
    val b: Int? = 128
    
    println(a === b) // false
    println(a == b) // true
    
    val aa: Int? = 127
    val bb: Int? = 127
    
    println(aa === bb) // true
    println(aa == bb) // true
}
  • Non-nullable numerical types (e.g., Int, Double):
    • Represented as primitives on the JVM.
    • === and == comparisons are equivalent (compare values, not references).
  • Nullable numerical types (e.g., Int?, Double?):
    • Boxed on the JVM.
Share Improve this question edited Nov 21, 2024 at 11:34 Pshemo 124k25 gold badges191 silver badges274 bronze badges asked Nov 21, 2024 at 9:33 Greg_MGreg_M 6151 gold badge7 silver badges12 bronze badges 7
  • 13 @YoucefLAIDANI: No, == is precisely what the OP is trying to compare here: whether the two values are references to the same object. – Jon Skeet Commented Nov 21, 2024 at 9:39
  • 1 Please could you show the Kotlin code? If you're using == there, that may be the issue - you want to use === for reference equality, to be equivalent to the Java code. – Jon Skeet Commented Nov 21, 2024 at 9:40
  • 6 @YoucefLAIDANI: But claiming "this is not correct" is, itself, incorrect when the OP is trying to check for reference equality. When that's your aim, using == instead of equals is entirely correct. – Jon Skeet Commented Nov 21, 2024 at 9:49
  • 2 I think you need to check the docs for number literals. kotlinlang.org/docs/numbers.html#literal-constants-for-numbers "On the JVM platform, numbers are stored as primitive types" try what your doing with a nullable type. eg Int? They actually have an example showing exactly what you want to do. – matt Commented Nov 21, 2024 at 10:04
  • 1 This question has nothing to do with string interning. It's about value caching of primitive wrappers. String interning is a different thing. – k314159 Commented Nov 21, 2024 at 10:30
 |  Show 2 more comments

2 Answers 2

Reset to default 5

Please read https://kotlinlang.org/docs/equality.html

For values represented by primitive types at runtime (for example, Int), the === equality check is equivalent to the == check.

As to "how?" or "why?" you can compare the bytecode for your java code with the kotlin one and see what happens. But Int in kotlin may be replaced by the primitive JVM integer at runtime, so referential equality isn't possible.

edit: They are in fact replaced by the JVM primitives in your case, see https://kotlinlang.org/docs/numbers.html#numbers-representation-on-the-jvm

The difference you're seeing between Java and Kotlin in the comparison of integer values (== or ===) comes from how both languages handle object references and value caching, particularly with primitive and boxed types.

In Java

Integer objects are boxed objects. When you write Integer x = 127;, Java uses a special feature called autoboxing where int values are converted into Integer objects. For values between -128 and 127, the Java Virtual Machine (JVM) uses a cache (a "cache" pool of objects), meaning that it will reuse the same Integer object for any Integer in that range. This is a performance optimization to avoid creating new objects for frequently used values.

In Kotlin

Primitive Types In Kotlin, Int is a primitive type and behaves differently from Integer in Java. When you assign x: Int = 127, Kotlin treats x as a primitive, which does not involve boxing or object creation. Hence, when comparing x and y, it checks if the values are the same, not whether they refer to the same object in memory. Since 127 == 127, it returns true.

Autoboxing and Caching When you use boxed Int (such as val xx: Int = 128 and val yy: Int = 128), Kotlin still ensures value-based equality for primitive values. The === operator in Kotlin checks referential equality (whether two references point to the same object), but since Int in Kotlin is actually a primitive type (and not boxed into Integer as in Java), the values themselves are directly compared rather than the references.

=== in Kotlin This checks if the two variables refer to the exact same object. Since Kotlin uses the Int type for primitive values, this comparison still returns true for values like 128, unlike Java where they would be different objects.

Why === returns true for both 127 and 128 Since Kotlin's primitive Int values are directly compared (instead of their references like Java's Integer), even if the value is 128, the comparison is still value-based, which results in true.

Java uses boxing for Integer objects, and caches values between -128 and 127. For values outside this range, new objects are created, leading to referential inequality.

Kotlin, on the other hand, treats Int as a primitive type and does not involve boxing for primitive values like 127 or 128. The === operator in Kotlin checks value equality for primitive types, not referential equality, so it will return true for both 127 and 128.

本文标签: Why does Integer caching behave differently in Kotlin compared to JavaStack Overflow