java – 字符串实习谜语
|
我正在与我的同事的下一个谜语挣扎:
public class App1 {
public static void main(String[] args) {
String s1 = "Ja".concat("va"); // seems to be interned?!
String s2 = s1.intern();
System.out.println(s1 == s2); // true
}
}
这输出是真的.我有点惊讶,因为看起来s1是实习生.但这不是常数表达,不是吗? 但后来我更加惊讶为什么以下打印错误. public class App2 {
public static void main(String[] args) {
String s1 = "Ja".concat("va"); // seems not to be interned?!
String s3 = new String("Java"); // this changes output
String s2 = s1.intern();
System.out.println(s1 == s2); // false
}
}
为什么引入s3会改变输出? 解决方法
以下是管理Java String对象wrt到String池的规则:
>使用String文字创建String对象时,JVM会检查池中是否已存在字符串文字.如果池中存在该对象,则返回相同的对象而不是新对象. 让我们回顾一下你的例子, String s1 = "Ja".concat("va");
如果你看一下String source中的concat操作,你会注意到它最后会调用new运算符. new String(buf,true) 因此,s1不会添加到字符串池中. 现在,让我们看一下实习生所在的行, String s2 = s1.intern(); 这里,s1上的intern方法从String池返回该对象(如果它不存在则创建).因此,s2包含String池中的对象. 同时,s1仍然包含旧对象而不是池中的对象.因此, Java 1.8.0_92-b14中的修改行为 Java 8中的行为已更改. Java编译器正在执行优化.如果在concat之后立即调用intern方法,Java 8将优化并在字符串池中创建字符串对象,并忽略我们在早期Java版本中见过的new的早期行为.请检查反编译代码的操作码中的优化(checkOne是App1,checkTwo是App2),
public static void checkOne();
descriptor: ()V
flags: ACC_PUBLIC,ACC_STATIC
Code:
stack=3,locals=2,args_size=0
0: ldc #2 // String Ja
2: ldc #3 // String va
4: invokevirtual #4 // Method java/lang/String.concat:(Ljava/lang/String;)Ljava/lang/String;
7: astore_0
8: aload_0
9: invokevirtual #5 // Method java/lang/String.intern:()Ljava/lang/String;
12: astore_1
13: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
16: aload_0
17: aload_1
18: if_acmpne 25
21: iconst_1
22: goto 26
25: iconst_0
26: invokevirtual #7 // Method java/io/PrintStream.println:(Z)V
29: return
LineNumberTable:
line 6: 0
line 7: 8
line 9: 13
line 10: 29
LocalVariableTable:
Start Length Slot Name Signature
8 22 0 s1 Ljava/lang/String;
13 17 1 s2 Ljava/lang/String;
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 25
locals = [ class java/lang/String,class java/lang/String ]
stack = [ class java/io/PrintStream ]
frame_type = 255 /* full_frame */
offset_delta = 0
locals = [ class java/lang/String,class java/lang/String ]
stack = [ class java/io/PrintStream,int ]
public static void checkTwo();
descriptor: ()V
flags: ACC_PUBLIC,locals=3,args_size=0
0: ldc #2 // String Ja
2: ldc #3 // String va
4: invokevirtual #4 // Method java/lang/String.concat:(Ljava/lang/String;)Ljava/lang/String;
7: astore_0
8: new #8 // class java/lang/String
11: dup
12: ldc #9 // String Java
14: invokespecial #10 // Method java/lang/String."":(Ljava/lang/String;)V
17: astore_1
18: aload_0
19: invokevirtual #5 // Method java/lang/String.intern:()Ljava/lang/String;
22: astore_2
23: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
26: aload_0
27: aload_2
28: if_acmpne 35
31: iconst_1
32: goto 36
35: iconst_0
36: invokevirtual #7 // Method java/io/PrintStream.println:(Z)V
39: return
LineNumberTable:
line 13: 0
line 14: 8
line 15: 18
line 17: 23
line 18: 39
LocalVariableTable:
Start Length Slot Name Signature
8 32 0 s1 Ljava/lang/String;
18 22 1 s3 Ljava/lang/String;
23 17 2 s2 Ljava/lang/String;
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 35
locals = [ class java/lang/String,class java/lang/String,int ]
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
