Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 字符串文字的行为令人困惑_Java_String_String Interning - Fatal编程技术网

Java 字符串文字的行为令人困惑

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

在下面的代码中,字符串文字的行为非常混乱

我能理解第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
      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