一、String创建的对象有两种,一种在缓冲池中创建,一种在堆中创建,以下列举说明:
1.String s=new String("abc");
创建对象时,首先括号中的abc会先查看缓冲池中是否存在abc,如果存在不再创建,不存在则在缓冲池中创建abc,然后,new会在堆中创建一个对象abc(无论堆中是否有abc,每new一次都会创建一个新的),这里的s指向的是堆里的abc,词条语句创建两个abc对象;
2.String s1="abc";
创建对象时,abc会直接到缓冲池中查看是否存在abc,如果存在不再创建,不存在则在缓冲池中创建abc,s1指向缓冲池中的abc;
二、案例
案例1.
①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);解析:①括号中abc查看在缓冲池中是否存在abc,不存在,则在缓冲池中创建一个,紧接着new会在堆中创建新对象abc,并且让s指向堆中abc;
②abc查看缓冲池中是否存在abc,存在,不再创建,s1直接指向缓冲池中的abc;
③括号中abc查看在缓冲池中是否存在abc,存在,不再创建,紧接着new会在堆中创建abc,并且让s2指向堆中创建新对象abc,每new一次创建一个新的,所以和s指向的不是一个;
④s指向堆中abc,s1指向缓冲池中abc,所以false;
⑤同理④,所以false;
⑥s1和s2都是指向堆中abc,但每new一次会创建一个新的abc,所以指向的不是同一个,故false;
案例2.
①String s = new String("abc"); ②String s1 = "abc"; ③String s2 = new String("abc"); ④System.out.println(s == s1.intern()); ⑤System.out.println(s == s2.intern()); ⑥System.out.println(s1 == s2.intern());解析:
intern()说明:返回对应这个字符串内容的那个缓冲池里的对象,如s1.intern()的执行流程是,在缓冲池里查找abc,如果找到,指向缓冲池里的对象,如果没有,在缓冲池中创建abc,并指向缓冲池里这个对象;
①②③同案例1中①②③;
④s指向堆中对象,s1指向缓冲池中的对象,故false;
⑤同理④,故false;
⑥s1和s2.intern()均指向缓冲池中的对象,并且指向的是同一个对象,故true;
案例3:
①String h = "hello"; ②String e = "hel"; ③String l = "lo"; ④System.out.println(h == "hel" + "lo"); ⑤System.out.println(h == "hel" + l);解析:
①hello查看缓冲池中是否存在hello,不存在,创建,并让 h 指向缓冲池中的hello;
②hel馋看缓冲池中是否存在hel,不存在,创建,并让e 指向缓冲池中的hel;
③lo查看缓冲池中是否存在lo,不存在,创建,并让 l 指向缓冲池中的 lo;
④"hel"+"lo"进行字符串连接,连接为”hello",并且查看缓冲池中是否存在hello,①中已经在缓冲池中创建了,故直接指向hello,并且和h指向的是同一个hello,故true;
⑤hel+ l =”hello“ 但此时是在堆里创建一个hello,并且使其指向堆中的hello,而h 是指向缓冲池中的hello,故false;
结论:+ 两端是字面量时,在缓冲池中创建对象,如果有一端不是字面量时,而是引用变量,那么在堆中创建对象;
《完》