为什么Java char使用UTF-16?

问题描述 投票:0回答:2

我一直在阅读有关 Unicode 代码点如何随时间演变的信息,包括 Joel Spolsky 的这篇文章,其中说:

有些人误以为 Unicode 只是一个 16 位代码,每个字符占 16 位,因此有 65,536 个可能的字符。这实际上是不正确的。

但是尽管阅读了所有这些,我还是找不到 Java 使用 UTF-16 的真正原因

char
.

UTF-8 不是比UTF-16 更高效吗?例如,如果我有一个包含 1024 个 ASCII 范围字符字母的字符串,UTF-16 将占用 1024 * 2 字节 (2KB) 的内存。

但是如果 Java 使用 UTF-8,它只是 1KB 的数据。即使字符串有几个字符需要 2 个字节,它仍然只需要大约 1 千字节。例如,假设除了这 1024 个字符之外,还有 10 个字符“字”(代码点 U+5b57,UTF-8 编码 e5 ad 97)。在 UTF-8 中,这仍然只需要 (1024 * 1 字节) + (10 * 3 字节) = 1KB + 30 字节。

所以这没有回答我的问题。 UTF-8 的 1KB + 30 字节显然比 UTF-16 的 2KB 少内存。

当然,Java 不对字符使用 ASCII 是有道理的,但是为什么它不使用 UTF-8,它有一个干净的机制来处理出现的任意多字节字符? UTF-16 看起来像是在任何具有大量非多字节字符的字符串中浪费内存。

我缺少 UTF-16 的一些充分理由吗?

java unicode utf-8 utf-16
2个回答
35
投票

Java 在 2004/2005 过渡到 UTF-16 之前使用了 UCS-2。当初选择UCS-2的原因主要是历史

Unicode 最初设计为固定宽度的 16 位字符编码。 Java 编程语言中的原始数据类型 char 旨在通过提供一种可以容纳任何字符的简单数据类型来利用这种设计。

这一点,以及 UTF-16 的诞生,由 Unicode FAQ 页面进一步解释

最初,Unicode 被设计为纯 16 位编码,旨在代表所有现代文字。 (古代脚本将用专用字符表示。)随着时间的推移,尤其是在添加了 14,500 多个复合字符以与旧集兼容之后,很明显 16 位不足以满足用户社区的需求。由此产生了 UTF-16。

正如@wero 已经提到的,使用 UTF-8 无法有效地完成随机访问。因此,权衡所有因素后,UCS-2 似乎是当时最好的选择,尤其是在那个阶段还没有分配补充字符的情况下。这使得 UTF-16 成为最简单的自然进程。


-1
投票

从历史上看,一个原因是随机访问或迭代字符串字符的性能特征:

UTF-8 编码使用可变数字 (1-4) 字节来编码 Unicode 字符。因此,通过索引访问字符:

String.charAt(i)
java.lang.String
使用的数组访问实现起来更复杂,速度也更慢。

即使在今天,Python 在内部对字符串使用固定宽度的格式,每个字符存储 1、2 或 4 个字节,具体取决于该字符串中字符的最大大小。

当然,这不再是 Java 的纯粹优势,因为正如 nj_ 解释的,Java 不再使用 fixed-with 格式。但在开发该语言时,Unicode 是一种固定宽度的格式(现在称为 UCS-2),这本来是一个优势。

© www.soinside.com 2019 - 2024. All rights reserved.