当我们创建 String 对象的时候,如果使用 new() 的方式来创建一个 String 对象,JVM 将会每次都会在 heap 内存中为我们创建的 String 对象开辟一个存储空间来进行存储。
但是,如果我们使用赋值方式创建 String 对象的话,JVM 首先将会对我们赋的值到 String Pool 中进行查找,如果找到的话,就返回已经存在这个值的引用。
如果没有找到,就创建一个新的 String 对象并且返回这个创建对象的引用。
例如,我们如果使用赋值方式将值 “HoneyMoose” 创建的话,我们有可能会得到的是已经存在值的内存地址让我们能够来重新利用已经划分的内存,也有可能是一个全新的内存地址。
简单来说,这 2 种方式创建的 String 字符串都是 String 对象,唯一不同的是 new 操作每次都会给出新的地址,另外的操作则不能每次都是新的内存地址。
要解释这种情况,我们可以用一个数据基本面试问题的题目来进行解释,就是为什么使用 == 进行字符串比较的时候有时候会得到 False 的值。
因为,我们都知道 == 比较的是地址,而不是 String 中存储的值。
考察下面的代码:
String first = "HoneyMoose";
String second = "HoneyMoose";
System.out.println(first == second); // True
在上面的初始化后比较中,我们会得到 True 的值,因为上面 2 个 String 的地址是相同的。
下面,我们再使用 new 关键字来创建 2 个新的 String 对象,然后再来比较 String 对象的引用:
String third = new String("HoneyMoose");
String fourth = new String("HoneyMoose");
System.out.println(third == fourth); // False
相同的,我们使用 new 的方式来创建对象,我们可以看到上面创建的 String 的地址是不相同的。
因此使用 == 计算的结果是 False。
String fifth = "HoneyMoose";
String sixth = new String("HoneyMoose");
System.out.println(fifth == sixth); // False
通常来说,我们建议对 String 对象初始化的时候,使用文字方式对 String 对象初始化,这样的话我们能够让 JVM 有机会对 String 初始化之前进行判断来完成内存优化而不需要重复创建相同的对象。