https://blog.csdn.net/zhuxinquan61/article/details/51952463
首先直接看这样的两个字符串的声明:
String s1 = new String("TestString");
String s2 = "TestString";
- 1
- 2
- 3
对于这样两个字符串的声明在内存中的分布如下图:
字符串s1由于是new的结果,那么首先s1作为一个变量会在栈内存中开辟空间用来保存该变量,然后在堆内存中开辟一块空间用来保存这个字符串对象,同时,也正是因为s1作为一个字符串,在开辟字符串对象空间的同时,在堆内存中也会把该字符串常量保存在字符串常量池当中,所以说,一次new的字符串对象会在堆内存当中产生两个字符串对象。
对于字符串s2这种初始化赋值的方式,首先会在字符串常量池当中进行寻找,如果字符串常量池当中包含该字符串,则直接将该变量指向该字符串常量,如果不包含该字符串,则会新创建一个字符串常量到字符串常量池当中。
上述两种字符串创建的方式,s1会创建两个字符串对象,其中一个是new在堆内存上的字符串对象,一个是在字符串常量池中保存的一份字符串,而s2有可能不用创建对象,若该常量字符串存在则不需要再次进行创建,若不存在则需要在字符串常量池当中进行创建。
接下来看一下字符串在编译期和运行器的分析比较
同样先来一段代码:
public class StringObject {
public static void main(String[] args) {
//eg1
String a = "a1";
String a1 = "a" + 1;
System.out.println(a == a1); //true
//eg2
String b = "b1";
int bb = 1;
String b1 = "b" + bb;
System.out.println(b == b1); //false
//eg3
String c = "c1";
final int cc = 1;
String c1 = "c" + cc;
System.out.println(c == c1); //true
//eg4
String d = "d1";
final int dd = getDd();
String d1 = "d" + dd;
System.out.println(d == d1); //false
}
public static int getDd(){
return 1;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30