It has been 629 days since the last update, the content of the article may be outdated.

String的注意事项

  • String的对象是不可变字符串对象
    • 结论:每次试图改变字符串对象实际上是新产生了新的字符串对象,变量每次都是指向了新的字符串对象,之前字符串对象的内容确实是没有改变的。因此说String的对象是不可变的。
  • 只要是以双引号:”…”方式写出的字符串对象,会在堆内存中的字符串常量池中存储。
    • s1与s2都是”…”方式创建的,都存储在堆内存中的常量池中。先前s1已经创建了”ABC”字符串对象,故后面创建的s2对象会直接指向s1创建的字符串对象。该情况下s1和s2的地址是一样的。
    • 但是通过new方式创建字符串对象,每new一次都会产生一个新的对象放在堆内存中。
java
1
2
3
String s1 = "ABC";
String s2 = "ABC";
System.out.println(s1 == s2); //true

引用类型String在堆内存中的存储方式

有趣的思考题

示例1

解析:String s2 = new String("abc");如下行代码运行时创建了:2个对象

首先是”abc”在堆内存中的常量池中被创建,new String() 在堆内存中再创建一个Sting对象存储"abc"

java
1
2
3
4
5
6
7
public static void main(String[] args) {
String s2 = new String("abc");
//如下代码创建了:0个对象
String s1 = "abc";
//s2指向的还是堆内存中的String对象,而不是在常量池中的
System.out.println(s1 == s2); //false
}

示例2

解析:如下代码是进行了运算,是会在堆内存中new一个新的对象出来的,地址不相同

java
1
2
3
4
5
6
7
public static void main(String[] args) {
String s1 = "abc";
String s2 = "ab";
//如下代码是进行了运算,是会在堆内存中new一个新的对象出来的,地址不相同
String s3 = s2 + "c";
System.out.println(s1 == s3); //false
}

示例3

解析:最后输出结果为true。Java存在编译优化机制,程序在编译时:"a" + "b" + "c"就会直接转成"abc",从而提高程序的执行性能

java
1
2
3
4
5
public static void main(String[] args) {
String s1 = "abc";
String s2 = "a" + "b" + "c";
System.out.println(s1 == s2); //true
}

链接

封面图来源:https://www.pixiv.net/artworks/74345419