首先String不属于8种基本数据类型,String是一种引用数据类型,其默认值是null。
String类在Java中是一个不可变类,字符串在被创建后不能被更改。
通过上图,我们可以得出:
1)String类被final关键字修饰,意味着String类不能被继承;字符串一旦创建就不能再修改。
2)String类实现了Serializable、CharSequence、 Comparable接口。
3)String实例的值是通过字符数组实现字符串存储的。
通过源码,我们也就可以知道为什么String类不可变:
1、底层char[]数组有final修饰,意味着这个数组不能扩容等,来达到存更多的字符。
2、char[]数组是私有的,程序员无法直接操作这个char[]数组,而且String没有提供这样的方法,来修改char[]数组的元素的值。
3、String提供的所有的方法,对字符串的修改都是给你返回一个新的字符串对象。
字符串对象底层的存储:
JDK1.9之前:底层是用 char[ ] 存储
JDK1.9之后:底层选用 byte[ ] 存储
虚拟机内存主要分为三块:
堆:存放对象实例和数组。
栈:存放基本类型,以及对象的引用。
方法区:“类”被加载后的信息,常量、静态变量存放在这儿。
在Java的内存分配中,总共3种常量池,分别是Class常量池、运行时常量池、字符串常量池。
字符串的分配和其他对象分配一样,是需要消耗高昂的时间和空间的,而且字符串使用的非常多。JVM为了提高性能和减少内存的开销,在实例化字符串的时候进行了一些优化:使用字符串常量池。每当创建字符串常量时,JVM会首先检查字符串常量池,如果该字符串已经存在常量池中,那么就直接返回常量池中的实例引用。如果字符串不存在常量池中,就会实例化该字符串并且将其放到常量池中。由于String字符串的不可变性,常量池中一定不存在两个相同的字符串。
字符串常量池在哪里?(Oracle官方虚拟机HotSpot)
(1)JDK1.6以及之前:方法区中
(2)JDK1.7:挪到堆中,即在堆中单独划分了一块字符串常量
(3)JDK1.8:从堆中挪出,挪到一个 “元空间meta space”,即类似于方法区
字符串常量池(String Pool)是方法区中的一块存储空间,当创建一个字符串时,如果池中已经存在相同的字符串就会返回其引用,而不是在堆中创建一个新对象。(此处指的是字面量创建字符串,用new关键字创建的话,无论池中存不存在都会在堆中创建一个新对象)
字符串常量池:
1、当直接创建一个字符串时,变量会到字符串常量池中去寻找该字符串,如果找到了,该变量指向该字符串;如果没有找到,会用 byte[ ]拼接成所需的字符串,然后放入常量池中并指向它。
2、使用 new 关键字创建字符串,会在堆区创建一个 String 对象,而且底层是用 byte[ ] 数组拼接的,这个 String 对象并没有放入字符串常量池中,而是在堆中,该变量指向该对象的地址。
字符串的拼接
字符串对象可以使用“+”连接其他对象。其中字符串连接是通过 StringBuilder(或 StringBuffer)类及其append 方法实现的,对象转换为字符串是通过 toString方法实现的,该方法由 Object 类定义,并可被 Java 中的所有类继承。
使用“+”连接符时,JVM会隐式创建StringBuilder对象,这种方式在大部分情况下并不会造成效率的损失,不过在进行大量循环拼接字符串时则需要注意。
这样由于大量StringBuilder创建在堆内存中,肯定会造成效率的损失,所以在这种情况下建议在循环体外创建一个StringBuilder对象调用append()方法手动拼接。
与此之外还有一种特殊情况,也就是当"+"两端均为编译期确定的字符串常量时,编译器会进行相应的优化,直接将两个字符串常量拼接好。
拼接的注意事项:
1、常量与常量的拼接结果在常量池中
2、只要其中有一个是变量,结果就在堆中
3、如果拼接的结果调用 intern() 方法,就在常量池中
intern方法
直接使用双引号声明出来的String对象会直接存储在字符串常量池中,如果不是用双引号声明的String对象,可以使用String提供的intern方法。intern 方法是一个native方法,intern方法会从字符串常量池中查询当前字符串是否存在,如果存在,就直接返回当前字符串;如果不存在就会将当前字符串放入常量池中,之后再返回。
参考资料
https://blog.csdn.net/liyu4352502/article/details/100772926
https://www.cnblogs.com/niujifei/p/11303420.html
https://blog.csdn.net/ifwinds/article/details/80849184