Strng创建对象

下面说的常量池都是指字符串常量池,字符串常量池存在运行时常量池之中(在JDK7之前存在运行时常量池之中,在JDK7已经将其转移到堆中),运行时常量池从永久代移到了元空间中。

String a = new String("ab");

此时创建了两个对象,常量池中创建了ab对象,堆内存中也创建了ab对象,此时引用指向堆内存中的对象。

String a = "ab";

此时先去常量池中寻找有没有ab这个值,如果有就直接将引用指向它,如果没有,则在常量池中创建这个ab对象,引用指向它。

intern()方法调用,如果字符串常量池中已经存在一个等于String对象的字符串,就直接返回这个字符串对象的引用。如果字符串常量池中不存在该对象,则将此对象放到常量池中,返回新建字符串对象的引用。

String c = new String("b") + new String("a");

会创建六个对象

1.new StringBuilder对象用来做拼接

2.堆内存中创建new String("b")

3.常量池中创建b对象

4.堆内存创建new String("a")

5.常量池中创建a对象

6.最终需要调用StringBuilder中的toString()方法,而toString方法底层调用的是new String来实现的因此又创建了一个对象ab,但是注意点是这里调用toString()方法只会在堆内存创建对象,不会在常量池中创建对象

intern的难点案例;

String s = new String(1); s.intern(); String s2 = "1"; System.out.println(s==s2);

1.6至1.8都会返回false

此处和下面的对应起来作比较,这里的intern没有将常量池中引用指向堆内存的new是因为在调用intern方法之前,常量池中已经有对象了,下面调用的是toString(),这里直接new的

分析:第一步在堆内存和常量池中都会创建一个1的对象,此时s指向堆内存1。第二步调用Intern方法,但是此时常量池中已经存在1这个对象,而且并没有让s指向这个intern,所以此时s还是指向的堆内存中的1。第三步,以为常量池中已经存在1这个对象,因此直接将说引用指向这常量池中地对象。第四步判断为false,一个指的堆内存,一个指的常量池中的对象。

String c = new String("b") + new String("a"); c.intern(); String d = "ab"; System.out.println(c==d);

1.6版本返回false,1.7和1.8返回的是true

和刚刚的区别就是第一步用了拼接最后调用的toString(),常量池中没有创建对象,通过第二步的intern方法才在常量池中创建了ab对象。1.6返回false的理论同上,因为一个指向的堆内存,一个指向的常量池。

1.7和1.8相对于1.6区别在于,字符串常量池移到了堆内存中,为了节省常量池的空间,在调用intern()方法时,如果堆内存中此时1通过new创建了ab对象,那么就直接引用指向这个new出来的对象,也就是说此时常量池中保存的是new出来的那个对象的地址,并没有创建一个新的对象。


__EOF__

本文作者liuliu的小家
本文链接https://www.cnblogs.com/liu-jin/p/17398127.html
关于博主:hello~好久不见,喜欢的话点个赞吧
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Bepowerful  阅读(45)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示