目录
引出问题
在理解这两个的区别之前,我们先看一段代码
public static void main(String[] args) {
String s1 = new String("abc");
String s2 = "abc";
System.out.println(s1 == s2);
String s3 = s2.intern();
System.out.println(s2 == s3);
}
如果你对上面的2个输出有所疑惑的话,看完这篇文章,相信你会有所收获。
理解内存分布
我们先来理解一下字符串常量和字符串变量以及他们对象的创建过程,相信会方便你理解上面的比较。
字符串常量:是放在字符串常量池里的,在代码里也就是"abc"
字符串对象:是一个对象,是放在堆里的,在代码里也就是"new String("abc")"
接下来是他们在内存中的分布
解释分析:
内存分布解析
String s1 = new String("abc")
首先在栈中开辟一个地址s1存放堆中new String("abc")的地址,然后new这个String的对象。在new这个对象的时候,要先去判断字符串常量池中是否有"abc"这个常量。如果有,直接在对象中存储这个常量的地址。如果没有,则需要去常量池中先创建这个常量,再将这个常量的内存存储到对象中。
String s2 = "abc"
首先在栈中开辟一个地址s2,存放即将存放的常量的地址。依旧是先去常量池中去判断是否存在这个常量,不同的是,这次放入的是直接存入栈中的s1引用。
String s3 = s2.intern()
引用创建如上文,String对象的intern方法,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。
结果分析
比较s1 和 s2时,由于s1的对象是new出来的,所以存在堆中。而s2存储的地址是处于字符常量池中的方法区中,所以比较s1和s2的地址比较,必然是false;
比较s2 和 s3时,由于s3是由s2.intern()得来,intern我们已经知道是直接返回的常量的引用。所以s2和s3的存储的地址是一样的,固然返回true
好了,这次的文章就到这里,喜欢的同学可以点赞收藏,遇到问题,可以评论,或者留言,我一定会第一时间给到回馈,感谢观看!!
注:本文为本人学习时心得分享,有讲错或者需要改正的地方,请指正,我会虚心接受