//package com.test;public class TestString {
  public static void main(String[] args) {
    String s = new String("abc");
    String s1 = "abc";
    String s2 = new String("abc");
    
    System.out.println(s == s1);
    System.out.println(s == s2);
    System.out.println(s1 == s2);
    
  }
}//这行代码运行结果返回都是false,我奇怪的是既然s1和s同是指向s开始时创建的那个"abc",为什么
//System.out.println(s == s1);也是返回false?

解决方案 »

  1.   

    由于String同时使用了享元模式和不变模式,而String类维护了一个共享区,用来保存String对象。一般的通过new创建的对象比如是String a=new String("a"),只是在堆上,但是不处于这个共享区。而像String aa="aa"这样的立即数形式,是存在于共享区的。
    共享区保证了内容一样的字符串只存在一个,但是这只是对共享区而言,而对付非共享区的堆空间,即使是你的String内容是一样的,都是不同的对象。归根到底,所有的对象都是new出来的,立即数形式的"aa"也是一样,它隐含调用了String的一个方法来确保这个立即数形式的String是在共享区中的,这个方法就是public String intern()
    一般的,通过new创建的String,都是在堆上,包括我刚刚说的共享区,其实也是在堆上。你要吧一个String放在共享区中,需要通过String对象的intern方法,这个方法检查共享区里有没有与当前的String内容相同的对象(用equals判断的),如果没有,就在共享区里面创建一个,然后,它的返回值是,这个共享区中的对象。
    当我们写String x="a",其实底层应该是String x=new String("a").intern();所以 你上面写的s,s1,s2是三个不同的对象。
    不知道这样说能否清楚。
      

  2.   

    好像叫String 规范还是什么来的```
    用简写法
    String s="abc"这样生成的String,要是内容相同的话,则引用指向同一个对象``String s=new String("abc")无论之前有没有和他内容相同的,它都会开新建一个对象``
    所以三个引用指向的对象都不同```
      

  3.   

    LS的所言极是! 原来String   s1   =   "abc";把s1发配到享元区(String pool)了! 剩下的那两个s 和s2才被孤零零的在堆那里歇凉, 是我原来没有String pool这个概念,认为只要是相同的内容String类就会自动把新的引用指向那里。谢谢各位
      

  4.   

    LS是指2楼....  不过没关系啦,大家都是对的,不过fox_for_cloud实在是说得很明白