有人能解释这两个引用如何指向堆中的同一个对象吗?
String strA = new String("APPLES");
String strB = new String("APPLES");
答案 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)
您很可能会遇到字符串实习
此外,字符串文字始终引用类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更容易检测到这种情况。