【问题标题】:What is the Java's internal represention for String? Modified UTF-8? UTF-16?Java 对 String 的内部表示是什么?修改过的UTF-8? UTF-16?
【发布时间】:2012-03-30 17:47:50
【问题描述】:

我在 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在内存中使用一个char需要多少字节?

请告诉我哪个是正确的以及它使用了多少字节。

【问题讨论】:

  • stackoverflow.com/questions/4655250/…,这可能会回答你的问题。
  • Java 使用什么和 JVM 在内存中使用什么不必相同。看我的回答。
  • 你的Java(官方)信息的主要来源应该是java.sun.com! (尽管有 stackoverflow
  • @CarlosHeuberger 你绝对是对的!感谢您的建议:-)
  • 请注意,Java 语言规范没有明确定义字符串在使用时的存储方式,只是它们是不可变的(并且有一些提示可能会被保留)。所以任何答案都应该明确列出运行时,因为它们中的大多数没有,所以它们都是 tosh。

标签: java string encoding utf-8 utf-16


【解决方案1】:

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

String 和 StringBuilder 等在 Java 中的表示是 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 在内存中使用一个 char 多少字节?

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

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

【讨论】:

  • Java 序列化(和类文件)use modified CESU-8 though,这是一个修改后的 UTF-8。
  • 新 URL:docs.oracle.com/javase/8/docs/api/java/lang/String.html 注意:Java 9 应该会在明年发布。 ;)
  • @KorayTugay 好问题。这是 3 年前,但我想我指的是对象中的填充。添加一个 char 字段最多可以添加 8 个字节,并带有填充/对象对齐。
  • @Praxeolitic 字节序是处理器原生的。通常很少,但几乎没有关系。
  • 这个答案已经过时了。一般来说,你不应该假设知道内部表示是什么样的。如果要保存此答案而不报告 BS,则应使用特定的运行时或这种情况下的运行时对其进行更新。
【解决方案2】:

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

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

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

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

-XX:-CompactStrings

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


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

另见:


回答您的具体问题:

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

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

Java 在内存中使用一个 char 多少字节?

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

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

请告诉我哪个是正确的以及它使用了多少字节。

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

【讨论】:

    【解决方案3】:

    UTF-16。

    来自http://java.sun.com/javase/technologies/core/basic/intl/faq.jsp

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

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

    【讨论】:

    • 此答案中链接的常见问题解答不再存在。我能找到的最接近的是:docs.oracle.com/javase/8/docs/technotes/guides/intl/…。但请注意,如果您仔细解析引用的文本和我找到的链接,则实际上都没有说明内部String 表示是什么。 (他们说一个字符串代表一个char 序列,但这不是一回事。)事实上......对于最近的Java 实现,String 的默认实现使用byte[] 而不是@987654327 @内部。大家可以查看OpenJDK源码看看。
    【解决方案4】:

    char 的大小为 2 个字节。

    因此,我会说 Java 使用 UTF-16 来表示内部字符串。

    【讨论】:

    • @tchrist 怎么样? Java中的一个字符怎么可能是4个字节?
    • @KorayTugay Unicode 字符(代码点)是介于 0 和 0x10FFFF 之间的值。
    • @tchrist Java 会将 4 字节的 Unicode 字符视为 2 个 Java 字符。请看:tugay.biz/2016/07/stringlength-method-may-fool-you.html
    • 其实你的推断是不正确的。最近的实现不(总是)将 UTF-16 用于内部字符串表示。
    【解决方案5】:

    Java 在内部将字符串存储为 UTF-16,每个字符使用 2 个字节。

    【讨论】:

    • 这个答案不正确。因为 Java 使用 UTF-16,每个 Unicode 字符要么是 2 个字节,要么是 4 个字节。
    • @tchrist UTF-16 编码如何以 4 个字节结束? UTF-16 不是总是 2 个字节吗?
    • @KorayTugay 不,UTF-16 是 2 字节或 4 字节。它是一种可变宽度编码,就像 UTF-8 一样。只有过时的 UCS-2 是 2 个字节,而且早就死了。
    • UT-16 的编码单元始终为 2 个字节。但字符本身需要 1 个代码单元或 2 个代码单元,因此需要 2 或 4 个字节。
    • @LudovicKuty “字符”是一个渲染和特定于语言的概念 - 它可以占用 大量 个代码点来组成单个字符,因此一个字符可以占用高达数百字节。所以它更像是“代码点本身 - 在 UTF-16 中 - 需要 2 或 4 个字节”尝试在互联网上搜索“unicode composition”。如果您正在构建 UI 框架或实现渲染逻辑,您通常只关心“字符” - 例如字符从哪个代码点开始或字符串中有多少个字符。
    【解决方案6】:

    java 有 18 种国际语言可用,并且遵循 UNICODE 字符集,它包含了 18 种国际语言可用的所有字符和 包含65536个字符。而java遵循UTF-16,所以java中char的大小是2个字节。

    【讨论】:

    • Java 中 Unicode 字符的大小在 2 字节和 4 字节之间变化,这取决于我们是否在平面 0 中。
    • A char 是 2 个字节,但一个字符(没有打字机字体的字符)是 2 或 4 个字节,正如 @tchrist 提到的那样
    猜你喜欢
    • 2013-03-04
    • 2012-10-08
    • 2011-01-23
    • 1970-01-01
    • 1970-01-01
    • 2018-12-31
    • 2019-07-31
    • 2017-09-24
    • 1970-01-01
    相关资源
    最近更新 更多