Java对String的内部表示是什么?修改后的 UTF-8?UTF-16?

2022-08-31 19:52:00

我在Java的内部表示中搜索了String,但是我有两种材料看起来可靠但不一致。

一个是:

http://www.codeguru.com/cpp/misc/misc/multi-lingualsupport/article.php/c10451

它说:

Java 使用 UTF-16 作为内部文本表示形式,并支持对 UTF-8 进行非标准修改以进行字符串序列化。

另一个是:

http://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8

它说:

Tcl也使用与Java相同的修改后的UTF-8[25]来表示Unicode数据的内部表示,但对外部数据使用严格的CESU-8。

修改后的 UTF-8?还是 UTF-16?哪一个是正确的?Java在内存中用多少字节来表示字符?

请让我知道哪一个是正确的,它使用了多少字节。


答案 1

Java 使用 UTF-16 作为内部文本表示

Java中String和StringBuilder等的表示形式是UTF-16。

https://docs.oracle.com/javase/8/docs/technotes/guides/intl/overview.html

文本在 Java 平台中是如何表示的?

Java编程语言基于Unicode字符集,并且有几个库实现了Unicode标准。Java 编程语言中的基元数据类型 char 是一个无符号的 16 位整数,可以表示 U+0000 到 U+FFFF 范围内的 Unicode 码位,或 UTF-16 的代码单位。Java 平台中表示字符序列的各种类型和类 - char[],java.lang.CharSequence 的实现(如 String 类)和 java.text.CharacterIterator 的实现 - 都是 UTF-16 序列。

在 JVM 级别,如果您使用的是(对于 Java 6 的某些更新,这是缺省值),则实际的内存中表示形式可以是 8 位 ISO-8859-1,但仅适用于不需要 UTF-16 编码的字符串。-XX:+UseCompressedStrings

http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html

并支持对字符串序列化的 UTF-8 进行非标准修改。

默认情况下,序列化字符串使用 UTF-8。

Java在内存中用多少字节来表示字符?

如果忽略在对象中填充的需要,则 A 始终为两个字节。char

注意:码位(允许字符> 65535)可以使用一个或两个字符,即2或4个字节。


答案 2

您可以通过查看 OpenJDK 中该类的相关版本的源代码来确认以下内容。(对于一些非常旧的Java版本,部分是在本机代码中实现的。源代码不公开。java.lang.StringString

在 Java 9 之前,Java 的标准内存中表示形式是 UTF-16 代码单元保存在 .Stringchar[]

在 Java 6 update 21 及更高版本中,有一个非标准选项 () 来启用压缩字符串。此功能在 Java 7 中已被删除。-XX:UseCompressedStrings

对于 Java 9 及更高版本,默认情况下,的实现已更改为使用紧凑表示形式。命令文档现在是这样说的:Stringjava

-XX:-紧凑型字符串

禁用“压缩字符串”功能。默认情况下,此选项处于启用状态。启用此选项后,仅使用单字节字符的 Java 字符串将在内部表示,并使用 ISO-8859-1 / Latin-1 编码存储为每个字符一字节的字符串。这将仅包含单字节字符的字符串所需的空间量减少 50%。对于至少包含一个多字节字符的 Java 字符串:这些字符串使用 UTF-16 编码表示并存储为每个字符 2 个字节。禁用“压缩字符串”功能将强制使用 UTF-16 编码作为所有 Java 字符串的内部表示形式。


请注意,经典的“压缩”或“紧凑”字符串从未使用过 UTF-8 编码作为表示形式。修改后的 UTF-8 用于其他上下文;例如,在类文件中,以及对象序列化格式。String

另请参阅:


要回答您的具体问题:

修改后的 UTF-8?还是 UTF-16?哪一个是正确的?

UTF-16或依赖于实际数据的自适应表示;见上文。

Java在内存中用多少字节来表示字符?

单个使用 2 个字节。由于可能的填充,可能会有一些“浪费”,具体取决于上下文。char

A 是每个字符 2 个字节加上填充到(通常)8 个字节的倍数的对象标头(通常为 12 个字节,包括数组长度)。char[]

请让我知道哪一个是正确的,它使用了多少字节。

如果我们谈论的是现在,就不可能给出一个笼统的答案。这将取决于Java版本和硬件平台,以及长度和(在某些情况下)字符是什么。实际上,对于某些版本的Java,它甚至取决于您如何创建.StringStringString