String s1 = "hello";//在常量池查找“hello”,没有就新建一个。s1是一个引用,指向常量池的helloString s2 = "hello";//s1,s2都指向常量池中的同一个“hello” String s3 = new String("hello");//新建一个对象,存放在堆区中,每次调用都新建一个对象。
System.out.println(s1==s2);//true 这个是判断引用s1,s2是否指向同一个空间,并不能判断字符串的内容是否相等。
System.out.println(s1==“hello”);//System.out.println(s2==s3);//false 引用指向的不是同一个地址空间
System.out.println(s3==“hello”);//false 一个在变量池里一个在堆区。System.out.println(s3.equals("hello"));//true 这个函数才是用来判断字符串内容用的System.out.println(s1.equals("hello"));//trueString s4 = “ab”+"cd";//编译时优化成s4=“abcd” String s5 = "ab"; String s6 = “cd”; String s7 = s5 + s6; //*[1]
*[1] 当执行s5+s6时,JVM首先会在堆中创建一个StringBuilder类对象,同时用s5指向的限定字符串对象完成初始化,然后调用append方法完成对s6所指向的限定字符串的合并操作,接着调用StringBuilder的toString()方法在堆中创建一个String对象,最后将刚生成的String对象的堆地址存放在局部变量s7中。而s4存储的是常量池中“abcd”所对应的限定字符串对象的地址。 所以如果判断s4==s7得到的结果会是false。
1.限定字符串对象和常规字符串对象
限定字符串对象就如s1所指的对象,常量池只有它一个,一般不能在常量池添加一个一模一样的。
常规字符串对象如s3所指的对象,可以创建若干个数据域中存储的字符串一模一样的对象。
2.intern()的用法——把常规字符串对象转化成限定字符串对象
String sa = new String("hello"); String sb = sa.intern(); System.out.println(sa==sa.intern);//false System.out.println(sb=="hello");//true
intern()在这里做了一件事,在常量池寻找“hello”,如果有,sa.intern()返回它的地址,若没有,在常量池添加一个,并且返回它的地址。