两段代码
String s1 = "a";
String s2 = s1 + "b";
s2.intern();
String s3 = "ab";
System.out.println(s2 == s3);与
String s1 = "a";
String s3 = "ab";
String s2 = s1 + "b";
s2.intern();
System.out.println(s2 == s3);第一段代码打印true 第二段打印false 请问为什么?
String s1 = "a";
String s2 = s1 + "b";
s2.intern();
String s3 = "ab";
System.out.println(s2 == s3);与
String s1 = "a";
String s3 = "ab";
String s2 = s1 + "b";
s2.intern();
System.out.println(s2 == s3);第一段代码打印true 第二段打印false 请问为什么?
s2.intern();
String s3 = "ab";
System.out.println(s2 == s3);
与
String s1 = "a";
String s3 = "ab";
String s2 = s1 + "b";
s2.intern();
System.out.println(s2 == s3);
一个初始为空的字符串池,它由类 String 私有地维护。当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并返回此 String 对象的引用。
它遵循以下规则:对于任意两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true
public String intern()返回字符串对象的规范化表示形式。
一个初始为空的字符串池,它由类 String 私有地维护。 当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并返回此 String 对象的引用。 它遵循以下规则:对于任意两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true。 所有字面值字符串和字符串赋值常量表达式都使用 intern 方法进行操作。字符串字面值在 Java Language Specification 的 §3.10.5 定义。
返回:
一个字符串,内容与此字符串相同,但一定取自具有唯一字符串的池。--------------------------------------------------------------------------------
public class StringTest2
{
public static void main(String [] args)
{
String s1 = "a";
String s2 = s1 + "b";
s2.intern();
String s3 = "ab";
System.out.println(s2.equals(s3));
System.out.println(s2 == s3);String s4 = "a";
String s6 = "ab";
String s5 = s4 + "b";
s5.intern();
System.out.println(s5.equals(s6));
System.out.println(s5 == s6);}
}
lz到底是怎么得到一个true一个false的结果的我很好奇
明明是两个false啊
public static void main(String[] args) {
t1();
t2();
}
public static void t1() {
String s1 = "a";//因为 "a"为常量所以编译的时候 "a"就被放入字符串常量池中
String s2 = s1 + "b";//因为s2=s1+b,"b"为常量被放入长字符串常量池中,但是s1为变量所以s2整体不能被放入 常量池中
s2.intern();//上句执行后,s2="ab",调用intern()方法后,发现字符串常量池中 没有"ab",所以在常量池中加入常量"ab"并把s2的引用放入池中。
String s3 = "ab";//s3执行的时候,系统发现字符串常量池中有"ab"所以把地址给s3,这里的地址就是s2的地址。
System.out.println(s2 == s3);//两个地址相同所以输出true。
} public static void t2() {
String s1 = "a";//因为 "a"为常量所以编译的时候 "a"就被放入字符串常量池中
String s3 = "ab";//因为"ab"是常量,所以在于编译的将"ab"放入字符串常量池中,地址为s3的。
String s2 = s1 + "b";//s2中因为有变量s1所以不能确认地址。
s2.intern();//这句执发现常量池中有"ab"但是返回引用S2没有接收所以还是以前地址。
System.out.println(s3 == s2);//这里所以是false.
}
}
String s2 = s1 + "b";
s2.intern();
String s3 = "ab";
System.out.println(s2 == s3);这段代码,执行完第二句 String s2 = s1 + "b"; s2应该是在堆里的吧?
String s3 = "ab"; 这个s3直接指向跟s2同一位置的堆里了??
怎么会有不同结果呢? 我是jdk 1.7
楼主可以去找找一些关于String的字符串池的资料。
再就是有点凌乱的是,我今天把JDK中的SRC包里的String源文件翻出来了,发现intern()方法是native的所以我的结论为推论,大家看看就得哈。
但是这个“ab”的地址和s2指向的地址相同,所以返回true.
字符串常量池中就会多了一个“ab”他的地址就是s2指向的地址。
懒得跟你说,自己看字节码:
public static void test1(){
String s1 = "a";
String s2 = s1 + "b";//s2是用StringBuilder的toString()生成的新字符串
s2.intern();
String s3 = "ab"; //s3是从常量池加载的常量
System.out.println(s2 == s3);//绝对不可能==
}
public static void test1();
Code:
Stack=3, Locals=3, Args_size=0
0: ldc #4; //String a
2: astore_0
3: new #5; //class java/lang/StringBuilder
6: dup
7: invokespecial #6; //Method java/lang/StringBuilder."<init>":()V
10: aload_0
11: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
14: ldc #8; //String b
16: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: astore_1
23: aload_1
24: invokevirtual #10; //Method java/lang/String.intern:()Ljava/lang/String;
27: pop
28: ldc #11; //String ab
30: astore_2
31: getstatic #12; //Field java/lang/System.out:Ljava/io/PrintStream;
34: aload_1
35: aload_2
36: if_acmpne 43
39: iconst_1
40: goto 44
43: iconst_0
44: invokevirtual #13; //Method java/io/PrintStream.println:(Z)V
47: return
public static void test2(){
String s1 = "a";
String s3 = "ab"; //这是常量池的常量
String s2 = s1 + "b";//这是StringBuilder的toString()生成的新字符串
s2.intern();
System.out.println(s2 == s3);//绝对不可能==
}
public static void test2();
Code:
Stack=3, Locals=3, Args_size=0
0: ldc #4; //String a
2: astore_0
3: ldc #11; //String ab
5: astore_1
6: new #5; //class java/lang/StringBuilder
9: dup
10: invokespecial #6; //Method java/lang/StringBuilder."<init>":()V
13: aload_0
14: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: ldc #8; //String b
19: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: invokevirtual #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
25: astore_2
26: aload_2
27: invokevirtual #10; //Method java/lang/String.intern:()Ljava/lang/String;
30: pop
31: getstatic #12; //Field java/lang/System.out:Ljava/io/PrintStream;
34: aload_2
35: aload_1
36: if_acmpne 43
39: iconst_1
40: goto 44
43: iconst_0
44: invokevirtual #13; //Method java/io/PrintStream.println:(Z)V
47: return
第二个s2 和 s3当然就不是同一个对象啦
如果把第二个的“s2.intern();”语句改为s2 = s2.intern(); 第二个结果也是true啦
http://blog.csdn.net/zhangerqing/article/details/8093919
public static void main(String[] args) {
String a = "abc";
String b = "b";
a.substring(1, 2);
System.out.println(a);
System.out.println(a.equals(b));
}
同理可得结果啥。有不对的,求大神嘲讽。