Java-String字符串的内存结构
本文参考自:公众号 程序新视界
原文链接:
https://mp.weixin.qq.com/s/jC3Gv3Fi0bo0d7rP5ngqpw
字符串通常的创建方式有两种:
- new关键字创建
- 通过引号直接赋值
这两种形式的字符串创建在内存上是有区别的。
使用引号直接赋值
使用引号直接赋值创建字符串时,会先去常量池中查找该字符串是否已经存在,如果不存在的话先在常量池创建对象,然后返回引用地址;如果存在,则直接返回。
使用new关键字创建
使用new关键字创建字符串时,创建的对象是分配在堆中的,栈中的引用指向该对象。
通过new关键字创建String对象,内存中会创建几个对象?
- 如果常量池中已经存在了"hello",则只创建一个对象在堆中
- 如果常量池中不存在,则先要在常量池中存储"hello",再在堆中创建对象并指向字符串常量池中的"hello",就创建了两个对象在堆中
字符串的拼接
字符串拼接分两种情况
- 使用+号拼接引号创建的字符串对象
- 使用+号拼接new关键字创建的字符串对象
使用+号拼接引号创建的字符串对象
例如:
String s1 = "hello" + "world";
String s2 = "helloworld";
System.out,println(s1 == s2);//true
对于s1字符串使用+号拼接引号创建的字符串对象,Java编译器会进行优化,操作是将字符串拼接,然后存入常量池的为"helloworld",根据上面使用引号创建字符串对象,可知s1和s2都指向常量池中同样的地址。
使用+号拼接new关键字创建的字符串对象
例如:
String s1 = new String("hello") + new String("world");
对于使用+号拼接new关键字创建的字符串对象,Java编译器也会进行优化操作,操作是:先创建一个StringBuilder,然后调用append的方法进行拼接,最后再调用toString方法生成字符串对象。最后通过toString方法生成的这个字符串,在常量池中是不存在的,那么可以理解为使用+号拼接new关键字创建的字符串对象,返回的始终是一个新对象。
测试输出内容如下:
public class TestK {
public static void main(String[] args) {
String s1 = "hello"+"world";
String s2 = "helloworld";
String s3 = new String("hello")+new String("world");
String s4 = new String("hello")+new String("world");
System.out.println(s1 == s2); //true
System.out.println(s1 == s3); //false
System.out.println(s3 == s4); //false
}
}