两段代码
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 请问为什么?

解决方案 »

  1.   

    你应该写成s2=s2.intern()才能完成你要的效果.第一个为什么是true呢?就关系到java虚拟机开辟内存的问题了.也就是说第一个为true是个巧合.
      

  2.   

    s2.intern();   先引用和后引用时不同的效果的
      

  3.   

    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);
     
    一个初始为空的字符串池,它由类 String 私有地维护。当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并返回此 String 对象的引用。 
    它遵循以下规则:对于任意两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true
      

  4.   

    http://www.iteye.com/topic/1112592http://www.iteye.com/topic/774673http://www.ticmy.com/?p=69
      

  5.   

    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);}
    }
      

  6.   

    内存地址不同吧 所以false  
      

  7.   

    好吧,楼上没有自己跑一遍程序的都弱爆了
    lz到底是怎么得到一个true一个false的结果的我很好奇
    明明是两个false啊
      

  8.   

    由于引用intern()的先后顺序吧
      

  9.   

    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.
    }
    }
      

  10.   

    我是没看明白各位的回复啊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同一位置的堆里了??
      

  11.   

    我自己测试运行的结果确实是 一个 true 一个 false ;  大家都自己测试了吗?
    怎么会有不同结果呢? 我是jdk 1.7
      

  12.   

    以上是我跑的程序结果,我不知道为啥和楼上的结果不同,我也没有说我是正确的,只是个人意见。
    楼主可以去找找一些关于String的字符串池的资料。
    再就是有点凌乱的是,我今天把JDK中的SRC包里的String源文件翻出来了,发现intern()方法是native的所以我的结论为推论,大家看看就得哈。
      

  13.   

    对s2放在堆里,因为String s2 = s1 + "b";执行的结果是 s2="ab";,所以执行s2.intern();发现字符串常量池中没有字符串常量“ab”,于是就把“ab”常量加到字符串常量池中,同时他的地址也带过去了,所以你在执行String s3 = "ab"; 的时候发现常量池中有常量"ab",于是S3的引用就指向字符串常量“ab”,
    但是这个“ab”的地址和s2指向的地址相同,所以返回true.
    字符串常量池中就会多了一个“ab”他的地址就是s2指向的地址。
      

  14.   


    懒得跟你说,自己看字节码:
    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
      

  15.   

    好了不要争了,刚看了6楼转的帖子,这个程序本来就有问题,原因取决于JVM,不同的JVM执行的结果不同,我承认楼上你很牛,我等着你给我解释JVM运行此程序原理,没有打架的意思哈,就是促进下你学习,正好我也去看看。
      

  16.   

    第一个由于调用s2.intern()把“ab”加入常量池了,所以s3 = “ab” 时并没有创建新的对象
    第二个s2 和 s3当然就不是同一个对象啦
    如果把第二个的“s2.intern();”语句改为s2 = s2.intern(); 第二个结果也是true啦
      

  17.   

    你那两个都打印false,你看看这篇文章吧,全面介绍Java字符串:
    http://blog.csdn.net/zhangerqing/article/details/8093919
      

  18.   

    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));
    }
    同理可得结果啥。有不对的,求大神嘲讽。