我有一个小程序在Java中测试文字行为。
public static void main(String[] args) {
String a = "foo";
String b = "foo";
String c = new String("foo");
System.out.println(a == b);
System.out.println(a.intern() == b);
System.out.println(a.intern() == a);
System.out.println(a == c);
System.out.println(c == b);
}
结果是:
true
true
true
false
false
字节码(javap-cMyClass)
public MyClass();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2; //String foo
2: astore_1
3: ldc #2; //String foo
5: astore_2
6: new #3; //class java/lang/String
9: dup
10: ldc #2; //String foo
12: invokespecial #4; //Method java/lang/String."<init>":(Ljava/lang/String;)V
15: astore_3
16: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;
19: aload_1
20: aload_2
21: if_acmpne 28
24: iconst_1
25: goto 29
28: iconst_0
29: invokevirtual #6; //Method java/io/PrintStream.println:(Z)V
32: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;
35: aload_1
36: invokevirtual #7; //Method java/lang/String.intern:()Ljava/lang/String;
39: aload_2
40: if_acmpne 47
43: iconst_1
44: goto 48
47: iconst_0
48: invokevirtual #6; //Method java/io/PrintStream.println:(Z)V
51: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;
54: aload_1
55: invokevirtual #7; //Method java/lang/String.intern:()Ljava/lang/String;
58: aload_1
59: if_acmpne 66
62: iconst_1
63: goto 67
66: iconst_0
67: invokevirtual #6; //Method java/io/PrintStream.println:(Z)V
70: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;
73: aload_1
74: aload_3
75: if_acmpne 82
78: iconst_1
79: goto 83
82: iconst_0
83: invokevirtual #6; //Method java/io/PrintStream.println:(Z)V
86: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;
89: aload_3
90: aload_2
91: if_acmpne 98
94: iconst_1
95: goto 99
98: iconst_0
99: invokevirtual #6; //Method java/io/PrintStream.println:(Z)V
102: return
}
问题)
1) 我看到system.out.println
证实了a和b是相同的对象以下两者之间有什么区别:System.out.println(a == b);
System.out.println(a.intern() == b);
2) 由于JVM在NonHeap PermanentGeneration InternetStrings中放入相同的String
文字,String
优化是否正在工作?这就是创建InternetString的原因吗?那么,为什么即使没有a.intern()
,这也是相等的:a==b
两者之间有什么区别:System.out.println(a==b);System.out.println(a.internal()==b);
只是第二个涉及完全不必要的方法调用。
由于JVM在NonHeap PermanentGeneration InternetStrings中放入相同的字符串文字,字符串优化是否正在工作?这就是创建InternetString的原因吗?那么,为什么即使没有.intern(),这也是相等的:a==b
因为编译器和JVM协同工作,可以自动插入字符串文字。编译器将它们放在类文件的一个称为"常量池"的部分中,JVM在加载类时将这些常量加载到内部池中。
只是为了让普通读者更清楚:在Java中比较字符串的正确方法是使用.equals
方法或类似方法,而不是==
。将==
与字符串实例一起使用通常是不正确的。OP可能在这里使用它是为了了解字符串是如何以及何时被插入的;在真正的代码中,你不会。(同样:new String("foo")
在最好的情况下几乎总是不必要的,而且更可能是一个坏主意。同样,除非你在考虑何时以及如何练习琴弦。)