String的疑惑-String对象在内存中的位置

“String倒底奇特在哪里?”关于这个问题本来想放过它的,但听说java面试经常考它,而且博友又给我提了不少珍贵的意见,所以准备在尽点力。

废话到此,下面正式开始



1.请看下面这幅图片:


是否觉得奇怪,在1处为true,2处为false!对java有所了解都知道“s1==s2"比较的并非它们在的值(那时该用:s1.equals(s2)),而是比较他们在内存中的地址!难道s1,s2引用的是内存中的同一个数据,呵呵,正是如此!

由于String对象在编程中使用的极为平凡,故而随着程序的增长,势必造成String常量占有了大量的内存,而且往往包含这大量的冗余。假设String与其他类的特性相同,势必造成如下局面:



从中不难看到,内存中充斥这大量的冗余常量"pig","dog",而实际上我们只需要两个常量就可以了。为了解决这个问题,从而使java更高效的使用内存,JVM留出一块特殊的内存区域——“String常量池”。(对String够优待吧)

所以当编译器遇到String s1 = "pig";时,首先检查String常量池中是否有存在"pig", 如果没有,则将pig放入常量池中,如下图:



继续,当编译器遇到String s2 = "pig";时,首先检查String常量池中是否有存在"pig", 如果发现相同的常量"pig", 则只是把指向常量池中现有的,而不创建任何新的String对象。如下:



到此,我们应该可以弄明白为什么1处运行的结果是true了吧!

同时,我们也可以弄明白我上一篇文章的疑惑了,如果常量池中的发生了变化,则s1,s2将会同时变化,这也太可怕了吧,所以java绝对不允许出现这种情况!这也是我们常说的那句话:String对象不可改变!
PS:由于担心String常量池出现问题,String类被标识为final。

下面这个例子可能更加让你无法质疑,我就不在这里废话了:


public class Test {

public static void main(String[] args) {

String s1 = "pig";

Person person = new Person();
person.name = "pig";

System.out.println(person.name == s1);// 输出为true

}

}


Person.java



public class Person {
public String name;

}



至于2处为false,这表明在String s3 = new String("pig")这种情况下,因为我们使用了new 关键字,所以将在常规内存(非String常量池)中创建了一个新的String对象,并且将引用它(到此和普通的对象一样)。此外,常量"pig"将放置在池内。

众多面试答案中所说的String s3 = new String("pig");创建了两个对象,一个引用(句柄)是否指如下状态:(这里只是猜测,希望哪位高人给个正确答案,或者验证方法,小弟在此先行谢过!)



s3==s4比较的是s3,s4引用对象的地址,自然不相同,所以2处运行为false。



参考资料:《SCJP学习指南》

本文出自 “sunfish 翻车鱼” 博客,请务必保留此出处[b][color=red]http://sunfish.blog.51cto.com/417500/113108[/color][/b]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值