You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin字符串场景下引用相等与结构相等的相关疑问咨询

提问内容

我目前对*structural equality(结构相等)的理解是,它会比较对象的类型与内容。
对于
Referential equality(引用相等)而言,它比较的是两个对象的内存地址。另外如果是primitive type(原始类型)*的var变量,只要内容相同,引用相等比对结果就会为true。
根据官方文档说明:

数字、字符和布尔值在运行时可以表示为原始值,但对用户来说,它们看起来和普通类没有区别。

所以我认为String在运行时应当按照对象处理。
但我在实际测试中,对两个内容相同的字符串做引用相等比对时,返回结果为true,测试代码如下:

fun main(){
    val name1 = "123"
    val name2 = "123"

    println(name1 == name2) //true, structural equality which is same type and same content (same as equals)

    // checks if left and right are same object --> referential equality
    var name3 = "123"
    println(name1 === name3) //true ????????
    // should print false. String is basic type and not primitve
    
    var Arr: IntArray = intArrayOf(1,2,3)
    var Arr2: IntArray = intArrayOf(1,2,3)
    println(Arr === Arr2) // prints false, arrays are basic type
}

另外我还有一个疑问:Kotlin中的两种相等性比对为什么没有区分val和var?二者本质上属于不同类型的对象。
麻烦大家指出我的理解误区,我应该是忽略了某个很基础的知识点,多谢。


解答

1. 为什么内容相同的字符串字面量引用相等比对返回true

这是JVM平台的字符串常量池优化导致的,和字符串本身是不是原始类型无关:

  • 你代码中所有直接写死的"123"这类编译期可确定的字符串字面量,JVM会自动将其存入字符串常量池,相同内容的字面量会复用池中的同一个对象,所以name1、name2、name3实际上指向的是同一个对象,===比对自然返回true。
  • 如果要验证字符串的引用差异,可以使用运行时生成的字符串,测试如下:
val name1 = "123"
val name4 = String(charArrayOf('1','2','3')) // 运行时新建的字符串对象
println(name1 == name4) // 输出true,结构相等
println(name1 === name4) // 输出false,引用不等,符合你的预期

至于IntArray的比对结果为false是正常的:数组对象不会被JVM自动缓存,每次调用intArrayOf都会生成新的堆对象,引用自然不同。

2. 为什么相等性比对不区分val和var

你对val和var的理解存在本质偏差:

  • val和var只是变量的修饰符,仅用来限制变量本身的可赋值性:val修饰的变量不能被重新赋值,var修饰的变量可以被重新赋值,二者只是对象引用的持有者,和它们指向的对象的类型、属性没有任何关系。
  • 两种相等性比对判断的是两个变量指向的对象的相等性,和变量本身是val还是var完全无关,自然不需要做区分。

3. 补充原始类型的运行时逻辑

Kotlin官方提到的数字、字符、布尔值可被表示为原始值,是JVM平台的专属优化:当这类类型的变量没有被当做对象使用(比如没有调用方法、没有声明为可空类型)时,JVM会将其映射为不存在引用概念的原始类型,此时的===本质就是值比对,所以相同值的比对结果为true,这个和字符串常量池的优化是完全不同的两个机制。


内容的提问来源于stack exchange,提问作者HARSHIT BAJPAI

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 17:36:05