为什么JDK 9中把String的char[]改成了byte[]?

简介: Java 9引入“Compact String”优化字符串存储:若字符均为Latin-1编码(单字节),则用byte[]存储,节省空间;否则仍用UTF-16。通过新增`coder`字段标识编码类型,提升存储效率并保持兼容性。

在Java 9之前,字符串内部是由字符数组char[]来表示的。

/* The value is used for character storage. */
private final char value[];

由于Java内部使用UTF-16,每个char占据两个字节,即使某些字符可以用一个字节(LATIN-1)表示,但是也仍然会占用两个字节。所以,JDK 9就对他做了优化。


这就是Java 9引入了"Compact String"的概念:


每当我们创建一个字符串时,如果它的所有字符都可以用单个字节(Latin-1)表示,那么将会在内部使用字节数组来保存一半所需的空间,但是如果有一个字符需要超过8位来表示,Java将继续使用UTF-16与字符数组。


Latin1(又称ISO 8859-1)是一种字符编码格式,用于表示西欧语言,包括英语、法语、德语、西班牙语、葡萄牙语、意大利语等。它由国际标准化组织(ISO)定义,并涵盖了包括ASCII在内的128个字符。

Latin1编码使用单字节编码方案,也就是说每个字符只占用一个字节,其中第一位固定为0,后面的七位可以表示128个字符。这样,Latin1编码可以很方便地与ASCII兼容。


那么,问题来了,所有字符串操作时,它如何区分到底用Latin-1还是UTF-16表示呢?


为了解决这个问题,对String的内部实现进行了另一个更改。引入了一个名为coder的字段,用于保存这些信息。

/**
 * The value is used for character storage.
 *
 * @implNote This field is trusted by the VM, and is a subject to
 * constant folding if String instance is constant. Overwriting this
 * field after construction will cause problems.
 *
 * Additionally, it is marked with {@link Stable} to trust the contents
 * of the array. No other facility in JDK provides this functionality (yet).
 * {@link Stable} is safe here, because value is never null.
 */
@Stable
private final byte[] value;

/**
 * The identifier of the encoding used to encode the bytes in
 * {@code value}. The supported values in this implementation are
 *
 * LATIN1
 * UTF16
 *
 * @implNote This field is trusted by the VM, and is a subject to
 * constant folding if String instance is constant. Overwriting this
 * field after construction will cause problems.
 */
private final byte coder;

coder字段的取值可以是以下两种:

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

在很多字符串的相关操作中都需要做一下判断,如:

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

private boolean isLatin1() {
    return COMPACT_STRINGS && coder == LATIN1;
}


目录
相关文章
|
7月前
|
消息中间件 架构师 Kafka
【架构师】如何做技术选型?
技术选型无绝对优劣,关键在于“更合适”。需综合评估功能满足度、可扩展性、安全性、性能等非功能性需求,同时考量使用人数、社区活跃度、迭代速度、学习与维护成本,以及与现有技术体系的匹配度,权衡利弊后做出最优选择。
330 4
|
7月前
|
druid Java 数据库连接
【Java架构必看】Mybatis用的什么连接池?
Mybatis内置Pooled、Unpooled和JNDI三种数据源,支持连接池的Pooled性能有限,存在空闲资源占用、调优困难和连接泄漏等问题。因此推荐使用更成熟的第三方数据源如Hikari、Druid等,以提升系统稳定性和性能。
278 0
|
7月前
|
架构师 微服务
【架构师】微服务的拆分有哪些原则?
微服务拆分需遵循七大原则:职责单一、围绕业务、中台化公共模块、按系统保障级别分离、技术栈解耦、避免循环依赖,并遵循康威定律使架构与组织匹配,提升可维护性与协作效率。
563 4
|
7月前
|
Java Spring
IDEA调出services窗口
本教程分两步指导:首先点击指定选项,然后在Templates中添加Spring Boot并应用,即可调出services窗口,快速完成配置。
430 11
|
7月前
|
存储 运维 安全
一篇文章带你了解什么是云计算,SaaS PaaS IaaS的区别
云计算将硬件与软件资源集中于云端,企业按需租用,实现弹性扩容、降低成本。相比本地部署,云服务在运维、安全、效率上优势显著,并通过SaaS、PaaS、IaaS分层提供灵活支持,助力企业高效发展。(238字)
775 3
|
5月前
|
关系型数据库 MySQL 数据库
【2026最新 架构环境安装篇二】Docker安装MySQL8详细教程
本文介绍了如何使用Docker快速部署MySQL 8.0数据库。内容包括拉取镜像、创建本地目录挂载数据与配置文件、启动容器并设置端口映射、环境变量及重启策略,最后通过命令进入MySQL容器进行操作,适合初学者快速搭建开发环境。(239字符)
965 0
|
6月前
|
弹性计算 人工智能 应用服务中间件
阿里云服务器最新收费价格表:含年付、月付及小时计费标准
今年阿里云服务器推出多重优惠活动,覆盖 ECS 云服务器、轻量应用服务器、GPU 服务器等主流机型,支持北京、上海、中国香港、新加坡、日本、美国等多地域部署。爆款配置性价比突出,轻量应用服务器低至 38 元 / 年,ECS 经济型服务器 99 元 / 年起,GPU 服务器小时计费 1.2 元起,满足个人开发者、企业及 AI 训练等不同场景需求。
|
7月前
|
Linux Python
Anaconda和Miniconda在Linux系统下迁移虚拟环境
将A服务器的Miniconda虚拟环境loonflow3通过`conda list --explicit`导出配置,并打包env目录为tar.gz文件,使用scp传输至B服务器后解压至对应路径,再激活环境即可完成迁移。
620 5
|
7月前
|
架构师 IDE Java
【Java架构师】Maven中lombok那点事
SpringBoot项目中Lombok需在maven-compiler-plugin中配置`annotationProcessorPaths`,确保编译期生成getter/setter等方法;而`excludes`则在打包时排除Lombok依赖,减小体积,因运行时已无需该库。
703 1