当我正在学习
java时,我已经知道,比较2个字符串的正确方法是使用equals而不是“==”.这一行
static String s1 = "a"; static String s2 = "a"; System.out.println(s1 == s2);
将输出true,因为jvm似乎优化了这个代码,以便它们实际上指向同一个地址.我试图证明这是使用我在这里发现的一个伟大的文章
http://javapapers.com/core-java/address-of-a-java-object/
但地址似乎不一样.我失踪了什么
import sun.misc.Unsafe; import java.lang.reflect.Field; public class SomeClass { static String s1 = "a"; static String s2 = "a"; public static void main (String args[]) throws Exception { System.out.println(s1 == s2); //true Unsafe unsafe = getUnsafeInstance(); Field s1Field = SomeClass.class.getDeclaredField("s1"); System.out.println(unsafe.staticFieldOffset(s1Field)); //600 Field s2Field = SomeClass.class.getDeclaredField("s2"); System.out.println(unsafe.staticFieldOffset(s2Field)); //604 } private static Unsafe getUnsafeInstance() throws SecurityException,NoSuchFieldException,IllegalArgumentException,IllegalAccessException { Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafeInstance.setAccessible(true); return (Unsafe) theUnsafeInstance.get(Unsafe.class); } }
解决方法
你没有丢失任何东西不安全的图书馆正在报告实际发生的情况.
字节码:
static {}; Code: 0: ldc #11; //String a 2: putstatic #13; //Field s1:Ljava/lang/String; 5: ldc #11; //String a 7: putstatic #15; //Field s2:Ljava/lang/String; 10: return
注意,这两个字符串都放在内存中的不同位置,13和15.
这些变量存储在内存中,哪个需要一个单独的地址,以及一个新的对象是否放在堆上是有区别的.在这种情况下,它会为两个变量分配两个单独的地址,但它不需要创建一个新的String对象,因为它识别同一个String文字.所以这两个变量都引用同一个字符串.
如果你想得到地址,你可以使用这个问题How can I get the memory location of a object in java?中的答案.确保您在使用前阅读注意事项,但我做了一个快速测试,似乎工作.