public class String {
public static void main(String[] args) {
//==比较的是两方存放的对象的内存地址,equals比较的是内容是否相等
String a = "hello2";
final String b = "hello";//因为是final,最先被初始化
String d = "hello";
String c = b + 2;
String e = d + 2;
System.out.println(a == c);//true,变量a和c在初始化的时候,都等于hello2,所以被认定为指向同一个地址,所以两个变量在比较地址的时候,地址相等。
System.out.println(e == a);//false,变量e在初始化的时候,指向地址不为hello,也不为hello2,而是“"hello"+2”的地址,所以这个地址与hello2,与hello都不同
System.out.println(e == d);//false
System.out.println(b == d);//true,变量d的地址被认定为指向final变量b的地址
System.out.println(a .equals(e) );//true,内容相同
//a,b,c,d,e,都存储在栈中,先从常量池中查找是否有“”中的字符串,如果有,直接引用,如果没有,先在常量池中创建这个字符串,再引用其地址回到栈中
//
String s1="abc";
String s2="abc";
System.out.println(s1 == s2);//true,s1和s2初始化的时候,被指定为同一个地址
s1=s1+"a";
System.out.println(s1 == s2);//false,当s1变化的时候,s1的指向的地址发生变化
s2=s2+"a";
System.out.println(s1 == s2);//false,当s2发生与s1相同变化的时候,s1和s2指向的地址仍然不同
//
String s3 = new String("xyz");
String s4 = new String("xyz");
System.out.println(s3 == s4);//false
//s3,s4都存储在栈中,但是会在堆中创建new String(“xyz”)对象,new String再去常量池中进行拷贝,所以s3和s4的判断地址相等的时候,是不会相等的
}
}
String s1 = new String("1") + new String("1");
String s2 = s1.intern();
String s3 = "11";
System.out.println(s3 == s1);
System.out.println(s3 == s2);
System.out.println(s1 == s2);
String s6 = new String("go") +new String("od");
String s7 = s6.intern();
String s8 = "good";
//s6=s6+1;只增加这一行,下面运行结果为:false,true,false
//s8=s8+1;增加两个,下面运行结果为:false,false,false
System.out.println(s6 == s7);
System.out.println(s7 == s8);
System.out.println(s6 == s8);
//s1在初始化的时候,在栈里面存储一个s1,在堆里面存储一个new String+new String,所以常量池里面只有一个1
//s2在初始化的时候,使用s1.intern(),
//关于intern方法,源码里的解释为:当调用 intern方法时,如果池已经包含一个等于此String对象的字符串(用equals(oject)方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并返回此String对象的引用
//意思就是s2在初始化的时候使用intern,那么就会在常量池中将s1对象加入到常量池中,所以常量池中的"11"的地址其实就是s1“当前”的地址,也就是说s2实际上指向了s1“当前”的地址
//那么s3在初始化的时候,在常量池找到的也是s1“当前”的地址,所以这个时候进行地址比较的时候,因为s2和s3引用的地址都是s1的,所以会相等
//s6,s7,s8也是一样的,s7使用intern以后,将"good"存入了常量池,s7,s8都指向的是当前的s6的地址。如果后续对s1,s2,s3,s6,s7,s8有更改的话,那么相应的地址也就会发生变化,但是常量池里的地址是不会变的。
引用一个图片帮助理解:
String str1="abc";
String str2="abc";
String str3="abc";
String str4=new String("abc");
String str5=new String("abc");
String s1="hello";
String s2=s1;
System.out.println(s1==s2);//true
s1=s1+1;
System.out.println(s2=="hello");//true
//这个例子表明了一个问题,s1的地址是可以变化的,而常量的地址是不变的。
总结:String这个引用类型的道道还是有不少的,一不注意可能就会发生奇奇怪怪的问题。