先简单介绍一下字符串的创建过程:创建字符串常量时,先从字符串常量池中搜索有没有已有的字符串,如果有,则将新建的对象指向这个字符串常量地址,若没有,则新创建一个字符串常量,并让新建的对象指向它。
我们先看一下代码,再介绍内存图
public static void main(String[] args) {
String s = new String("HelloWorld");
String s1 = "HelloWorld";
由于字符串“Helloworld”在第一次创建的时候,方法区里面的字符串常量池中并没有“HelloWorld”这个字符串,所以字符串常量池会创建1个“HelloWorld”常量,并且赋予它一个地址(例如0x2345)。
当我们创建s1的时候,由于“HelloWorld”已经存在了,所以会直接将他的地址(0x2345)传给s1。
那么他们的区别在哪呢,我们来看内存图:
这是其中三块空间的jvm内存图。
String s = new String("HelloWorld");
因为s 对象是通过new 出来的(调用了String的构造方法),在堆中创建了String s这个对象,它保存了字符串“Helloworld”的内存地址(0x2345),在main方法中的局部变量s 保存了所创建对象的地址(0x6446)
String s1 = "HelloWorld";
而这种创建方式是直接将字符串“Helloworld”的内存地址(0x2345)赋给了s1。
=========================================================
以下是对上面的验证:
public static void main(String[] args) {
String x = "Hello";
String y = "Hello";
System.out.println(x == y); //true
String x1 = new String("Hello");
String y1 = new String("Hello");
System.out.println(x1 == y1); // false
System.out.println(x1.equals(y1)); //true
}
因为使用“==”的方式来比较会直接比较两个字符串对象的地址值。由上面介绍,得出x 与 y 是指向的同一块地址,所以结果为true。
当我们使用“==”比较x1 与y1时,由于他们保存的是堆中所创建对象的地址,所以结果为false。当使用equals方法来判断他们时,由于堆中存储的字符串常量的地址是一样的,所以结果是true