一 String的基本特性
1.1 基本特性
1)String:字符串,使用一对“”引起来表示。
2)String声明为final,不可被集成。
3)String实现了Serializable接口:表示字符串是支持序列化的,实现了Comparable接口,表示String可以比较大小。
4)String在JDK1.8及以前内部定义了final char[] value 用于存储字符串数据, JDK9的时候改为:byte[]。
1.2 存储结构变更
1)String在JDK9正式将底层存储结构变更为:byte[] 加上编码标记,节约了一些空间。
// JDK9源码:String
public final class String implements java.io.Serilizable,Comparable<String>,CharSequence{
@Stable
private final byte[] value;
}
1.3 不可变性
1)String代表不可变的字符序列。简称不可变性。
2)当对字符串重新赋值的时候,需要重新指定的内存区域赋值,不能使用原有的value进行赋值。
3)当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
4)当调用String的replace()方法修改指定的字符或者字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
5)通过字面量的方式,区别于new,给一个字符串赋值,此时字符串值声明在字符串常量池。
1.4 字符串常量池
1)String的StringPool是一个固定大小的HashTable,默认值大小长度为1009。如果放进StringPool的String非常多,就会造成Hash冲突严重,从而导致链表会非常长,而链表长了之后会直接造成的影响就是当调用String.intern()时的性能会大幅度下降。
2)使用 -XX:StringTableSize 可以设置StringTable的长度。
3)在JDK1.6的时候,StringTable是固定的,就是1009长度,所以如果常量池中的字符串过多就会导致效率下降很快。StringTableSize设置没有要求。
4)在JDK1.7中,StringTable的长度默认值为60013,StringTableSize设置没有要求。
5)从JDK1.8开始,设置StringTable的长度的话,1009是可设置的最小值。
二 String的内存分配
2.1 概述
1)在Java中,有8种基本数据类型和一种比较特殊的类型String。这些类型为了让它们在运行的过程中更快,更节省内存,都提供了一种常量池。
2)常量池就类似于一个Java系统级别提高的缓存。8种基本数据类型的常量池都是系统协调的,String类型的常量池比较特殊。它的主要使用方法有两种:
直接使用双引号声明出来的String对象会直接存储在常量池中。如
String info = "abc";
如果不是双引号声明出来的String对象,可以使用String提高的intern()方法。
2.2 位置的变更
1)Java6以及之前,字符串常量池存放在永久代中。
2)Java7中Oracle工程师对字符串常量池的逻辑做了很大的改变,即将字符串常量池的位置调整到了Java堆内。
3)所有的字符串都保存在堆中,和其他普通对象一样,这样可以让你在进行调优应用时仅仅需要调整堆大小就可以了。
4)字符串常量池的概念原本使用得比较多,但是这个改动使得我们有足够的理由让我们重新考虑Java7中使用String.intern()。
5)Java8元空间,字符串常量池在堆中。
String的基本操作
字符串拼接操作
intern()的使用
StringTable的垃圾回收
G1的String去重操作