jdk11-String源码分析

本文详细分析了JDK11中String类的源码,包括char类型、属性、构造方法和常用方法。从JDK9开始,String的value字段由char[]变为byte[],以节省空间并提高性能,尤其是对于使用Latin1编码的字符。文章还介绍了如何在不同编码方式下存储和转换字符,以及String对象的性能优化策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

char类型

一、定义

二、属性

String类型的性能优化

三、构造方法

四、其他方法

length方法

isEmpty方法

charAt方法

codePointAt方法

codePointBefore方法

getChars方法

equals方法


在进行String源码分析之前,我们先来介绍一下char数据类型。

char类型

char类型用于表示单个字符。通常用来表示字符常量。是一个无符号十六进制的值,从u\0000到\uffff。

char数据类型是一个采用UTF-16编码表示Unicode代码点的代码单元。,关于UTF-16编码具体可参考 字符编码笔记:ASCII,Unicode , UTF-8,UTF-16和ISO8859-1(Latin-1)

下面有两个个概念。

代码点:代码点(code point)是指与一个编码表中的某个字符对应的代码值。在Unicode标准中,代码点采用十六进制书写,并加上前缀U+,例如U+0041就是字母A的代码点。

Unicode的代码点可以分成17个代码级别(code plane)。第一个代码级别称为基本的多语言级别(简称BMP),代码点从U+0000到U+FFFF,其中包括了经典的Unicode代码;其余的16个附加级别,代码点从U+10000到U+FFFFF,其中包括了一些辅助字符。

代码单元:在BMP中,每个字符用16位表示,称为代码单元(code unit)。辅助字符采用一对连续的代码单元进行编码。

因为一个char类型字符代码的是一个代码单元,而UTF-16编码辅助平面字符需要用两个代码单元来表示一个代码点。这可能会带来一些误解,因此,尽量避免用char类型。

一、定义

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence

从该类的声明中我们可以看出String是final类型的,表示该类不能被继承,同时该类实现了三个接口:java.io.Serializable、 Comparable<String>、 CharSequence

二、属性

@Stable
private final byte[] value;
private final byte coder;
private int hash; // Default to 0
private static final long serialVersionUID = -6849794470754667710L;

static final boolean COMPACT_STRINGS;
static {
    COMPACT_STRINGS = true;
}
@Native static final byte LATIN1 = 0;
@Native static final byte UTF16  = 1;
  • value表示用来存储字符串对象的值,这里用byte[],@Stable表示该数组不会为null,final表示字符串一旦被初始化后是不会被改变的。

  • coder表示编码方式,Latin1(1个字节)或者UTF16(2个字节或4个字节)。

  • COMPACT_STRINGS 默认将 COMPACT_STRINGS 设置为 true。而如果要取消紧凑的布局可以通过配置 VM 参数-XX:-CompactStrings实现。

  • hash:hash值,默认为0。

String类型的性能优化

从jdk9之后,value的类型由char[]数组变成了byte[]数组。那么为什么要做这样的优化呢?为了节省空间,提高String的性能。

char占用两个字节(16bit),比如字符A,则为0x00 0x41,前面8个bit就是浪费的。也就是说刚好ISO-8859-1(0~255)编码范围的字符都会浪费8个bit,之外的字符则不会浪费。

jdk9之后,用byte[]数组存储字符串,一个byte占一个字节,即8bit。

在不指定字符编码的情况下,会有两种编码方式,Latin1(ISO-8859-1)和UTF-16,当字符都在Latin1范围内的时候就采用Latin1编码方式(紧凑布局),否则使用UTF-16。使用Latin1编码方式的时候,用了byte[]数组之后相对于使用char[]数组,空间节省了一半。

因为改变了String的实现,使用了Latin1和UTF16编码方式,需要增加一个属性coder来表明使用的是哪种编码方式。LATIN1=0;UTF16=1。

字符串对象是 Java 中大量使用的对象,而且我们会轻易大量使用它而从不考虑它的代价,所以对其的空间优化是有必要的,Java9 开始对String类进行优化, 这能帮助我们减少字符串在堆中占用的空间,而且还能减轻GC压力。同时也能看到该空间优化对中文来说意义不大。

三、构造方法

String有很多构造方法,这里介绍几个常见的构造方法。

无参数的构造函数

public String() {
    this.value = "".value;
    this.coder = "".coder;
}

传入String的构造函数

@HotSpotIntrinsicCandidate
public String(String original) {
    this.value = original.value;
    this.coder = original.coder;
    this.hash = original.hash;
}

传入char[]数组的构造方法

public String(char value[]) {
    this(value, 0, value.length, null);
}

String(char[] value, int off, int len, Void sig) {
    if (len == 0) {
        this.value = "".value;
        this.coder = "".coder;
        return;
    }
    if (
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值