String中的等与不等问题,“==”和“new”
(摘录加总结------)
一、运行测试用例
在谈及String中的等与不等的问题时,必须得考虑到JVM中的一块重要的区域,即常量池。下面的两组代码的运行结果是不一样的:
(1)无new关键字
运行结果是true,等号右边是存储的String类型的数据,等号左边是指向这个数据的引用。"=="在Java比较的不是两个对象的值,而是比较两个对象的引用是否相等。
public class Test { public static void main(String[] args) { String str0 = "520"; String str1 = "520"; System.out.println(str0 == str1); } }
(2)有new关键字
运行结果是false,str2和str3是两个不同的引用,所以返回的false。
public class Test { public static void main(String[] args) { String str2 = new String("1314"); String str3 = new String("1314"); System.out.println(str2 == str3); } }
二、常量池
JVM中有一块区域很重要叫常量池。常量池中的数据是那些在编译期间就被确定,并被保存在已编译的.class文件中的一些数据。除了包含所有的8种基本数据类型(char、byte、short、int、long、float、double、boolean)外,还有String及其数组的常量值,另外还有一些以文本形式出现的符号引用。
(1)针对第一个例子的分析,谈Java栈:Java栈的特点是存取速度快(比堆块),但是空间小,数据生命周期固定,只能生存到方法结束。String str = “520”这样子的定义我们分等号左边和等号右边来看的话,等号右边的数据值是编译期间就可以被确定的,被保存在常量池中;这些数据在常量池中被保存也是具有其各自的地址的,等号左边的引用的内容就是这些数据在常量池中数据的地址;String这个是引用的类型。
栈有一个特点,就是数据共享。针对第一个例子,第五行String str0 = "520",编译的时候,在常量池中创建了一个常量"520",然后走到String str1 = "520",先去常量池中找有没有这个"520",发现有,str1也指向常量池中的"520",所以str0 == str1返回的是true,因为str0和str1指向的都是常量池中的"520"这个字符串的地址。当然如果String str1 = "521",就又不一样了,因为常量池中没有"521",所以会在常量池中创建一个"521",然后str1代表的是这个"521"的地址。分析了String,其实其他基本数据类型也都是一样的:先看常量池中有没有要创建的数据,有就返回数据的地址,没有就创建一个。
(2)针对第二个例子分析,Java虚拟机的解释器每遇到一个new关键字,都会在堆内存中开辟一块内存来存放一个String对象,所以str2、str3指向的堆内存中虽然存储的是相等的"1314",但是由于是两块不同的堆内存,因此str2 == str3返回的仍然是false。