Java 字符串文字的行为令人困惑
在下面的代码中,字符串文字的行为非常混乱 我能理解第1行、第2行和第3行是Java 字符串文字的行为令人困惑,java,string,string-interning,Java,String,String Interning,在下面的代码中,字符串文字的行为非常混乱 我能理解第1行、第2行和第3行是真的,但为什么第4行是假的 当我打印两者的哈希代码时,它们是相同的 class Hello { public static void main(String[] args) { String hello = "Hello", lo = "lo"; System.out.print((Other1.hello == hello) + " "); //line 1 Sys
真的,但为什么第4行是假的
当我打印两者的哈希代码时,它们是相同的
class Hello
{
public static void main(String[] args)
{
String hello = "Hello", lo = "lo";
System.out.print((Other1.hello == hello) + " "); //line 1
System.out.print((Other1.hello == "Hello") + " "); //line 2
System.out.print((hello == ("Hel"+"lo")) + " "); //line 3
System.out.print((hello == ("Hel"+lo)) + " "); //line 4
System.out.println(hello == ("Hel"+lo).intern()); //line 5
System.out.println(("Hel"+lo).hashCode()); //hashcode is 69609650 (machine depedent)
System.out.println("Hello".hashCode()); //hashcode is same WHY ??.
}
}
class Other1 { static String hello = "Hello"; }
我知道==
检查引用相等性,并在池中检查文本。我知道equals()
是正确的方法。我想了解这个概念
我已经检查过了,但解释不清楚
如果您能给我一个完整的解释,我将不胜感激。您已经知道。。。这只是因为引用…当字符串来自池时,它将具有相同的引用…但当您进行手动操作时,将生成一个具有新引用的新字符串
您可以检查此链接,查看其是否有以下代码
("Hel"+lo)) + " "
内部翻译为
new StringBuilder("Helo").append(new String(lo)).append(new String(" ")).toString()
因此,您可以看到,在不同字符串实例的帮助下,创建了一个全新的字符串实例。这就是为什么当它们指向堆中不同的内存位置时会出现错误的原因,这是因为这个实例中的comipler不够聪明,无法计算出它可以在相同的字符串文本中燃烧
Hashcode需要始终为相等的字符串返回相同的值(对其调用.equals返回true),因此将返回相同的结果。Hashcode与对象引用无关(==检查是引用比较器)。可能有两个对象,其中hashCode返回相同的值,equals运算符返回true,但==返回false。这是指它们是两个不同的对象,但具有相同的值
我认为第4行返回false的原因是它是在运行时计算的值,因此是一个不同的字符串实例,具有不同的引用。每一个类型的字符串都将被放入字符串池
本质上这意味着:如果编译器可以(轻松地)“计算”字符串的值,而无需运行程序,那么它将被放入池中(规则比这稍微复杂一些,并且有一些特殊情况,请参阅上面的链接了解所有细节)
第1-3行中的所有字符串都是这样
“Hel”+lo
不是编译时常量表达式,因为lo
是非常量变量
散列码是相同的,因为。这是和的契约所要求的,运行时通过连接计算的字符串是新创建的,因此是不同的
下面是一个链接:字符串文本保存在一个特殊内存中,如果它们完全相同,则指向相同的内存映射。如果不创建文字字符串,将创建一个新对象,这样它就不会指向该内存,所以引用也不会相同
class Hello
{
public static void main(String[] args)
{
String hello = "Hello", lo = "lo";
System.out.print((Other1.hello == hello) + " "); //line 1
System.out.print((Other1.hello == "Hello") + " "); //line 2
System.out.print((hello == ("Hel"+"lo")) + " "); //line 3
System.out.print((hello == ("Hel"+lo)) + " "); //line 4
System.out.println(hello == ("Hel"+lo).intern()); //line 5
System.out.println(("Hel"+lo).hashCode()); //hashcode is 69609650 (machine depedent)
System.out.println("Hello".hashCode()); //hashcode is same WHY ??.
}
}
class Other1 { static String hello = "Hello"; }
intern()方法告诉虚拟机将其放入内存的共享字符串文本映射中,以便下次执行该文本时,它将在那里搜索并指向它。第3行和第4行之间的区别如下
•由常量表达式计算的字符串在编译时计算,然后将其视为文本
•运行时通过连接计算的字符串是新创建的,因此是不同的
以上参考来自java规范。如果需要更多说明,请告诉我
字符串对象可以通过以下方式创建:
String str = new String("abcd"); // Using the new operator
// str is assigned with "abcd" value at compile time.
String str="abcd"; // Using string literal
// str is assigned with "abcd" value at compile time.
String str="ab" + "cd"; // Using string constant expression.
// str is assigned with "abcd" value at compile time.
String str1 = "cd";
String str = "ab"+str1; // Using string expression.
// str is assigned with "abcd" value at run time only.
Hashcode将仅在运行时根据字符串对象的内容进行计算 我终于知道答案了
阅读Java SE 8规范第15.21.3节参考等式运算符==和!=()
而==可用于比较字符串类型的引用,例如
相等测试确定两个操作数是否引用
相同的字符串对象
如果操作数不同,则结果为false
字符串对象,即使它们包含相同的字符序列(§3.10.5)。可以测试两个字符串s和t的内容
通过方法调用s.equals(t)实现相等
因此,以下代码:
class Test {
public static void main(String[] args) {
String hello = "Hello";
String lo = "lo";
System.out.println((hello == ("Hel"+lo))); // line 3
}
}
第3行中的语句(“Hel”+lo)返回在运行时通过串联计算的新字符串
*在运行时通过连接计算的字符串是新创建的,因此是不同的。
()
所以这个代码的结果是:
class Test {
public static void main(String[] args) {
String hello = "Hello";
String lo = "lo";
System.out.println((hello == ("Hel"+lo))); // line 3
}
}
将导致:
false
因为
此语句中的“Hello”对象:
String hello = "Hello";
System.out.print((hello == ("Hel"+lo)) + " ");
以及本声明中的(“Hel”+lo)对象:
String hello = "Hello";
System.out.print((hello == ("Hel"+lo)) + " ");
是不同的,尽管:
*它们都包含相同的序列字符,即“Hello”
*它们都有相同的哈希代码
*hello.equals((“Hel”+lo))将返回true
System.identityHashCode()
将由默认方法hashCode()
返回,这通常通过将对象的内部地址转换为整数来实现。+1表示好奇。。第一个问题很好,因为hashcode相等并不意味着对象标识。查看Javadoc中的Object.hashCode()。
如果您知道这一点,就不会导致共振级联场景!那么hello==(“Hel”+“lo”)-->true是什么意思呢?请你再深入一点。我不确定您是否正确在第3行中,我正在执行操作“Hel”+“lo”将创建新对象,但它仍然引用池中的“Hello”字符串,当添加“Hel”+lo,lo is字符串变量时,它将创建“Hello”,那么为什么不引用相同的池文字???@sanbhat+1到您的注释中,然后如何(Hello==(“Hel”+“lo”)+“”)-->true?:-)即使在这里附加了一个额外的字符串。错误的“”没有被附加,我在连接之前进行检查,查看大括号是否与您尝试查看反编译代码的方式相同?也许它能给我们一些启示???@saury:decompilation ca