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

新手上路,请多包涵

我在 Java 的内部表示中搜索了字符串,但我得到了两种看起来可靠但不一致的材料。

一个是:

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 在内存中为一个字符使用了多少字节?

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

原文由 Johnny Lim 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 853
2 个回答

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 级别,如果您正在使用 -XX:+UseCompressedStrings (这是 Java 6 的某些更新的默认设置)实际的内存表示可以是 8 位,ISO-8859-1 但仅适用于字符串不需要UTF-16编码。

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

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

序列化字符串默认使用 UTF-8。

Java 在内存中为一个字符使用了多少字节?

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

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

原文由 Peter Lawrey 发布,翻译遵循 CC BY-SA 4.0 许可协议

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

在 Java 9 之前, Java String 的标准内存表示是 UTF-16 代码单元保存在 char[] 中。

对于 Java 6 更新 21 及更高版本,有一个非标准选项 ( -XX:UseCompressedStrings ) 来启用压缩字符串。这个特性在 Java 7 中被移除了。

对于 Java 9 及更高版本String 的实现已更改为 默认 使用紧凑表示。 java 命令 文档 现在这样说:

-XX:-CompactStrings

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


请注意,经典、“压缩”或“压缩”字符串都没有使用 UTF-8 编码作为 String 表示。在其他情况下使用修改后的 UTF-8;例如在类文件中,以及对象序列化格式。

也可以看看:


回答您的具体问题:

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

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

Java 在内存中为一个字符使用了多少字节?

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

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

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

如果我们现在谈论的是 String ,则无法给出一般性答案。这将取决于 Java 版本和硬件平台,以及 String 长度和(在某些情况下)字符是什么。实际上,对于某些版本的 Java,它甚至取决于您创建 String 的方式。


综上所述, StringAPI 模型它既 是 UTF-16 代码单元序列 是 Unicode 代码点序列。作为 Java 程序员,您应该能够忽略“幕后”发生的一切。内部 String 表示(应该是!)无关紧要。

原文由 Stephen C 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题