public class StringDemo {
/**
* @param args
*/
public static void main(String[] args) {
String s1 = new String("abc");//这里会创建两个对象,两个对象内容都是abc。注意:s1是引用,不是对象。
/**
* 首先,查看string pool里面有没有"abc",如果没有,就生成一个"abc"对象放在string pool里面。
* new String("abc")是放在堆里面,它会因为new而再生成一个"abc"的对象放在堆里面。
* 这就造成了string池里面有一个内容为"abc"的对象,堆里面也有一个内容为"abc"的对象。
* s1指向堆里面这个对象,堆里面的对象是池里面的对象的“复制品”
*/
String s2 = "abc";
/**
* s2这一句执行完以后,内存中一个对象都没有生成。
* 由于在此之前,已经有一个内容为"abc"的对象存在于池中,所以它不会再去池中创建一个内容为"abc"的对象,而是直接指向池中的这个对象。
*/
String s3 = new String("abc");
/**
* 当执行到s3这一行时,仍然会首先去池中查看是否有内容为"abc"的对象。
* 发现,已经有了,于是不会再在池中创建内容为"abc"的对象。
* 通过new创建了一个对象在堆内存中,内容为池中的对象的内容。
* 然后,s3指向这个堆中的对象。
*/
System.out.println(s1==s2);
System.out.println(s2==s3);
System.out.println(s1==s3);
/**
* 综上所述,s1创建两个对象,s2没有创建对象,s3创建了一个对象。总共生成了三个对象,池中一个,堆中两个。
* s1指向堆内存中的对象,s2指向线程池中的对象,s3指向堆内存中的对象。
* 所以说,s1,s2,s3指向了不同对象,而"=="比较的是内存地址,所以说,三个各不相同。
*/
System.out.println(s1==s1.intern());
System.out.println(s2==s2.intern());
System.out.println(s1.intern()==s2.intern());
/**
* intern()的用法:如果当前字符串的值,在池中有相同内容的对象,则直接返回池中对象的地址。
* 不论是s2,s2,s3,他们的值在池中都有一个对象的,所以说,无论谁调用了intern()都会返回池中对象的地址,也就是同一个地址,而且是s2的地址。
* 所以说,结果是false,true,true
*/
System.out.println("-----------------------------------");
String hello = "hello";
String hel = "hel";
String lo = "lo";
System.out.println(hello=="hel"+"lo");
/**
* 当加号左右两边都是常量的时候,会先拼起来,再去池里面找有没有内容相同的对象,如果有就直接返回这个对象的地址,否则就创建。
* 很显然,池中已经有内容为"hello"的对象了,它的地址,就是hello的地址,所以结果为true.
*/
System.out.println(hello=="hel"+lo);
/**
* 如果加号两边只要有一个不是常量,它不会再去检查池,而是直接在堆中重新生成一个对象。显然,结果应为false。
*/
System.out.println(hello==hel+lo);
}
}