关于String 的一个问题

lyj0913 2012-11-20 06:30:13
两段代码
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 请问为什么?


...全文
499 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
浪羽清风 2012-11-30
  • 打赏
  • 举报
回复
s2.intern() 与s2.subString()用法差不多吧,你在用完s2.intern()要用一个字符串的引用来接着吧,不然相当于s2没有发生改变。 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)); } 同理可得结果啥。有不对的,求大神嘲讽。
云寂@ 2012-11-21
  • 打赏
  • 举报
回复
好吧,楼上没有自己跑一遍程序的都弱爆了 lz到底是怎么得到一个true一个false的结果的我很好奇 明明是两个false啊
依琳小师妹 2012-11-21
  • 打赏
  • 举报
回复
你那两个都打印false,你看看这篇文章吧,全面介绍Java字符串: http://blog.csdn.net/zhangerqing/article/details/8093919
  • 打赏
  • 举报
回复
内存地址不同吧 所以false
wendale309 2012-11-21
  • 打赏
  • 举报
回复
第一个由于调用s2.intern()把“ab”加入常量池了,所以s3 = “ab” 时并没有创建新的对象 第二个s2 和 s3当然就不是同一个对象啦 如果把第二个的“s2.intern();”语句改为s2 = s2.intern(); 第二个结果也是true啦
As_tiankong 2012-11-21
  • 打赏
  • 举报
回复
引用 22 楼 goldenfish1919 的回复:
引用 20 楼 wenshuai1988 的回复: 引用 15 楼 goldenfish1919 的回复:引用 14 楼 AS_TianKong 的回复:Java code?123456789101112131415161718192021public class Test { public static void main(String[] args) { t1(); ……
好了不要争了,刚看了6楼转的帖子,这个程序本来就有问题,原因取决于JVM,不同的JVM执行的结果不同,我承认楼上你很牛,我等着你给我解释JVM运行此程序原理,没有打架的意思哈,就是促进下你学习,正好我也去看看。
若鱼1919 2012-11-21
  • 打赏
  • 举报
回复
引用 20 楼 wenshuai1988 的回复:
引用 15 楼 goldenfish1919 的回复:引用 14 楼 AS_TianKong 的回复:Java code?123456789101112131415161718192021public class Test { public static void main(String[] args) { t1(); t2(); ……
懒得跟你说,自己看字节码: 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
wang371537391 2012-11-21
  • 打赏
  • 举报
回复
这个还木有遇到,巧合?
wenshuai1988 2012-11-21
  • 打赏
  • 举报
回复
引用 15 楼 goldenfish1919 的回复:
引用 14 楼 AS_TianKong 的回复:Java code?123456789101112131415161718192021public class Test { public static void main(String[] args) { t1(); t2(); } public static void t1(……
人家错了你到说出错在那啊?就在说大话,空话,有意思吗?人家说的多不见得对,但比你不说的强多了。
As_tiankong 2012-11-21
  • 打赏
  • 举报
回复
引用 16 楼 lyj0913 的回复:
我是没看明白各位的回复啊。。。 String s1 = "a"; String s2 = s1 + "b"; s2.intern(); String s3 = "ab"; System.out.println(s2 == s3); 这段代码,执行完第二句 String s2 = s1 + "b"; s2应该是在堆里的吧? String s3 = "ab"; 这个s3直……
对s2放在堆里,因为String s2 = s1 + "b";执行的结果是 s2="ab";,所以执行s2.intern();发现字符串常量池中没有字符串常量“ab”,于是就把“ab”常量加到字符串常量池中,同时他的地址也带过去了,所以你在执行String s3 = "ab"; 的时候发现常量池中有常量"ab",于是S3的引用就指向字符串常量“ab”, 但是这个“ab”的地址和s2指向的地址相同,所以返回true. 字符串常量池中就会多了一个“ab”他的地址就是s2指向的地址。
As_tiankong 2012-11-21
  • 打赏
  • 举报
回复
引用 15 楼 goldenfish1919 的回复:
引用 14 楼 AS_TianKong 的回复:
Java code?123456789101112131415161718192021public class Test { public static void main(String[] args) { t1(); t2(); } public static void t1() { ……

以上是我跑的程序结果,我不知道为啥和楼上的结果不同,我也没有说我是正确的,只是个人意见。
楼主可以去找找一些关于String的字符串池的资料。
再就是有点凌乱的是,我今天把JDK中的SRC包里的String源文件翻出来了,发现intern()方法是native的所以我的结论为推论,大家看看就得哈。
lyj0913 2012-11-21
  • 打赏
  • 举报
回复
我自己测试运行的结果确实是 一个 true 一个 false ; 大家都自己测试了吗? 怎么会有不同结果呢? 我是jdk 1.7
lyj0913 2012-11-21
  • 打赏
  • 举报
回复
我是没看明白各位的回复啊。。。 String s1 = "a"; String s2 = s1 + "b"; s2.intern(); String s3 = "ab"; System.out.println(s2 == s3); 这段代码,执行完第二句 String s2 = s1 + "b"; s2应该是在堆里的吧? String s3 = "ab"; 这个s3直接指向跟s2同一位置的堆里了??
若鱼1919 2012-11-21
  • 打赏
  • 举报
回复
引用 14 楼 AS_TianKong 的回复:
Java code?123456789101112131415161718192021public class Test { public static void main(String[] args) { t1(); t2(); } public static void t1() { String s1 = "……
写的多不见得写的对,这又不是写作文!
As_tiankong 2012-11-21
  • 打赏
  • 举报
回复
public class Test {
	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.
	}
}
岑逸 2012-11-21
  • 打赏
  • 举报
回复
由于引用intern()的先后顺序吧。。。
zgx_20120702 2012-11-20
  • 打赏
  • 举报
回复


这个……
zhaoming262350 2012-11-20
  • 打赏
  • 举报
回复
zhaoming262350 2012-11-20
  • 打赏
  • 举报
回复
intern
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);

}
}


加载更多回复(5)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧