创建字符串的两种方式
一种是通过初始化的方式创建:
String str = "Hello";
另一种是通过构造方法使用new关键字创建:String str = new String("Hello");
因为一个字符串就是一个对象,Java为了避免重复产生大量的字符串对象,设计了一个字符串池(String Pool),通过初始化方式创建的字符串都会存在于字符串常量池中,且其中的字符串不会重复,以便可以被共享使用。
Jdk1.6及之前: 有永久代,运行时常量池在永久代,运行时常量池包含字符串常量池。
Jdk1.7:有永久代,但已经逐步“去永久代”,字符串常量池从永久代里的运行时常量池分离到堆里。 Jdk1.8及之后: 无永久代,运行时常量池在元空间,字符串常量池里依然在堆里。
工作原理:
当使用初始化的创建方式创建对象时,JVM首先会检查字符串池中是否已经有了相应的值,如果有则不进行创建,直接返回字符串池中该字符串的引用地址。如果不存在则创建对象,并放入字符串池中,返回新创建的字符串的引用地址。
当使用new关键字创建字符串对象时,就会在堆内存中创建两个内存空间,并且其中一块堆内存将成为垃圾空间。(用了一次之后就不再使用,成为垃圾空间,会被JVM自动回收掉)
示例
String str1 = new String("Hello");①
String str2 = new String("Hello");②
String str3 = "Hello";③
String str4 = str3;④
理解字符串的不可变,字符串是一种不可变的对象,它的内容不可改变。
String str5 = "Hello"; str5+="!!";⑤//只是str5指向的内存空间发生变化了,这里会在字符串常量池中新建两个对象:"!!!"&"Hello!!!"
总结
两种创建方式的区别:
直接初始化的方式:只会开辟一块堆内存空间,并且该字符串对象自动保存到字符串常量池中以供下次直接使用。
构造方法:会开辟两块内存空间,不会自动保存到字符串常量池中,可以使用intern()方法手工入池。