String Str1= new String("java");
String Str3 = new String("java");
System.out.println(Str1==Str3);
第一行代码在str1
池和堆中创建内容为"java"
init的对象String
。现在Str3
会做什么?我知道它在堆中创建Str3
什么关于字符串池中的Str3
?第3行做什么?它检查String
池或堆区域中的相等性吗?我知道它给出了错误,但我的问题是,如果Str1和Str3存储在字符串池==应该给出正确的,因为引用是相同的。
答案 0 :(得分:2)
第一行代码在String池和堆中创建带有内容“java”init的对象str1。
实际上:
因此,实际上语句 only 会在堆中创建一个字符串对象。
现在Str3会做什么?
第二个语句在堆中创建一个字符串对象....
根据上面的解释,此语句中使用的“java”文字的字符串对象是先前创建的。 (实际上,如果查看字节码文件,您会发现文件的常量池中只有一个“java”字符串。因此,类加载器甚至不需要创建两个字符串实例和intern()
他们只创造了一个并实习。)
我知道它在堆中创建Str3在字符串池中的Str3怎么样?
不。所有字符串文字都在字符串池中创建,它会自动扣除它们。
第3行做什么?它是检查字符串池还是堆区域中的相等性?
不。它测试以查看对象引用是否相同;即如果它们是同一个物体。它实际上并没有测试它们的位置。
(你实际上无法直接测试String是否在池中。你甚至无法测试对象是否在堆中......如果JVM为你提供了一种分配对象的方法在(常规)堆之外。)
我知道它给出了错误,但我的问题是,如果Str1和Str3存储在String pool中==应该为true,因为引用是相同的。
它们不在字符串池中。它们是普通的堆对象。
以这种方式思考,==
返回false
的事实证明它们不是(两者)在字符串池中。因为如果它们都在字符串池中,则它们必须相同的String
对象。
以下是JLS对字符串文字和标识的说法:
“此外,字符串文字总是引用类
String
的相同实例。这是因为字符串文字 - 或者更一般地说,作为常量表达式的值的字符串(第15.28节) - 是”实习“以便使用String.intern
方法分享唯一的实例。”
当班级加载 1 时会发生这种实习。
1 - 规格没有说实习发生的时间。看来最近的JVM懒惰地解析了方法对String文字的引用;即,在字节码解释器第一次调用该方法时发生实习。但是,这并没有改变上述解释的实质内容。