这两个引用如何指向堆中的同一个Object?

时间:2014-08-13 07:20:34

标签: java

有人能解释这两个引用如何指向堆中的同一个对象吗?

String strA = new String("APPLES");
String strB = new String("APPLES");

4 个答案:

答案 0 :(得分:1)

是的,当java检测到相同的String时,它将使用相同的堆空间。

您可以在 byteCode

中清楚地看到这一点
 public static void main(java.lang.String[]);
Code:
      0: new           #21                 // class java/lang/String
      3: dup
      4: ldc           #23                 // String APPLES
      6: invokespecial #25                 // Method java/lang/String."<init>":
Ljava/lang/String;)V
      9: astore_1
     10: new           #21                 // class java/lang/String
     13: dup
     14: ldc           #23                 // String APPLES
     16: invokespecial #25                 // Method java/lang/String."<init>":
Ljava/lang/String;)V
     19: astore_2
     20: getstatic     #28                 // Field java/lang/System.out:Ljava/
o/PrintStream;
     23: invokevirtual #34                 // Method java/io/PrintStream.printl
:()V
     26: return

正如您所看到的,#23用于两个对象,这意味着它们位于同一个内存位置。

现在让我们看看不同的字符串

String strA = new String("APPLES");
String strB = new String("BANANA");

这个的byteCode是:

 public static void main(java.lang.String[]);
   Code:
      0: new           #21                 // class java/lang/String
      3: dup
      4: ldc           #23                 // String APPLES
      6: invokespecial #25                 // Method java/lang/String."<init>":
Ljava/lang/String;)V
      9: astore_1
     10: new           #21                 // class java/lang/String
     13: dup
     14: ldc           #28                 // String BANANA
     16: invokespecial #25                 // Method java/lang/String."<init>":
Ljava/lang/String;)V
     19: astore_2
     20: return

现在BANANA将位于不同的内存位置,如上面的byteCode所示。这是因为Java现在知道它与APPLES的不同之处在于它需要被定位/存储在不同的内存位置。

答案 1 :(得分:1)

您很可能会遇到字符串实习

  

3.10.5. String Literals

     

此外,字符串文字始终引用类String的相同实例。这是因为字符串文字 - 或者更常见的是作为常量表达式(第15.28节)的值的字符串 - 被“实例化”以便使用String.intern方法共享唯一实例。

还有方法String.intern供参考。

答案 2 :(得分:1)

String strA = new String("APPLES");
String strB = new String("APPLES");
System.out.println(strA.equals(strB));
System.out.println(strA == strB);

结果:

true
false

字符串是相同的,因为它们的所有字符都匹配,但它们不是相同的INSTANCE。它们是具有相同价值的完全不同的物体。

答案 3 :(得分:0)

两个新的String变量都没有指向堆上的同一个对象。由于您使用的是new运算符,因此它几乎总是在堆上分配对象。由于您使用它两次,它将创建两个不同的对象。 Rod_Algonquin和Patrick在他们的答案中部分正确,因为String Literal&#34; APPLES&#34;指向同一个对象,但该对象被传递给String构造函数。这两个变量不指向与String Literal相同的对象&#34; APPLES&#34;。编译时已知的所有字符串都在运行时被实现以节省空间。但是,除非使用String.intern。

,否则使用new创建的任何字符串都不会指向与文字相同的对象

编辑:虽然非常积极的JVM可能会优化此类情况,使所有引用都指向同一个对象,但据我所知,当前的JVM没有为使用new创建的任何String执行此操作。它似乎是一个无意义的优化,JVM可以做,因为它没有增加太多的好处,程序员可以比JVM更容易检测到这种情况。