要想了解这两种方式的区别,首先就得知道jvm底层有哪些区域,和String的创建原理
先借一张别人的图片:
可以看到,jvm主要分栈区,堆区,方法区。我们只要先了解一下方法区
方法区中,存储了每个类的信息(包括类的名称、方法信息、字段信息)、静态变量、常量以及编译器编译后的代码等。
了解完方法区后,我们要了解编译器创建String的过程。
String在创建对象时,会将字符串变成一个常量,如果是第一次创建会将这个常量存储到方法区。如果方法区中已经存在,则直接将常量的地址交给String对象。
所以,当使用直接方法创建String对象是
String str = “string”;虚拟机会直接将常量的地址交给变量str
而使用new的方法创建时,我们知道new出来的对象会存放在堆中,所以
String s = new String(“string”);
s存的是在堆中的引用,堆中的引用存储的是方法区String常量的地址。
可以根据一下代码来证明:
package cn.geezer.string;
public class StringCreate {
public static void main(String[] args) {
/*
* 直接创建,所以两个变量存储的地址都是一样的
* */
String str = "string";
String str1 = "string";
System.out.println(str == str1);
/*
*使用new的方式创建,两个变量存储的是堆中的引用地址,所以他们是不一样的
*
*/
String s = new String("String");
String s1 = new String("String");
System.out.println(s == s1);
}
}
Files (x86)\Java\jre\lib\rt.jar;E:\Java\笔记\Recall\java-recall\out\production\java-recall" cn.geezer.string.StringCreate
true
false
进程已结束,退出代码 0