java9后String使用byte[]数组存储改动要点记录

161 阅读1分钟

改动原因

最根本的改动目的是减少String占用的内存。
java8之前,String使用char[]存储,char占两个字节,但是很多时候String的字符我们可以用一个字节表示,使用char就会浪费。而byte只占一个字节,所以使用byte将会大大减少String的内存空间。

仅仅将char改为byte就行了吗

char使用的是UTF-16编码格式,占2个或4个字节;
如果要使用一个字节来表示一个字符,那么一定要用到ISO-8859-1LATIN1编码格式,所以java9的String,一定要具备两种编码格式,所以java9添加了coder来区分两种编码格式

@Native static final byte LATIN1 = 0;
@Native static final byte UTF16  = 1;

String.length()

java8之前,length()方法为:

public int length() {
    return value.length;
}

直接返回char[]数组的长度即可 而java9以后:

public int length() {
    return value.length >> coder();
}

byte coder() {
    return COMPACT_STRINGS ? coder : UTF16;
}

在byte[]数组长度的基础上,右移了coder()位, COMPACT_STRINGS压缩标志默认为true
如果我们想关闭COMPACT_STRINGS功能则可以使用-XX:-CompactStrings参数。
coder是编码格式的值,LAATIN1为0,UTF-6为1;
所以在LAATIN1编码格式一个字节表示情况下,字符串长度为byte数组长度
在UTF-16两个或四个字节表示情况下,字符串长度为byte数组长度/2

indexOf();

与length方法一样,indexOf方法也添加了编码格式的判断

public int indexOf(int ch, int fromIndex) {
    return isLatin1() ? StringLatin1.indexOf(value, ch, fromIndex)
                      : StringUTF16.indexOf(value, ch, fromIndex);
}