Java 为什么使用 UTF-16 而不是更节省内存的 UTF-8?

知乎 · · 51 次点击 · · 开始浏览    

因为当时 Java 选择的是 UCS-2,是一个定长的编码,在当时以单个码元能表示所有字符,以下标获取字符的开销基本等同于在数组中索引一个字符,用起来是最方便的,多占用的内存大小也是可以接受的。到了后来 UCS-2 无法表示所有 Unicode 字符的时候,过渡到了兼容它的 UTF-16 上也是最自然以及迁移成本最低的选择,这很好理解。

至于 UTF-16 浪费内存的问题,在 JEP 254 Compact Strings 中优化了这个问题,Java 9 已经实现了这个 JEP。翻翻源码就能看到,现在 String 内部是存储了一个 byte[],以及对应的编码标记,而不再是 char[]

public final class String {
   ...
  private final byte[] value;
  private final byte coder;
  ...
}

现在只有在存在 latin1 无法表示的内容的时候,String 才会以双字节存储字符,大大降低了内存的浪费。

Java 的这个选择在当时来说其实很不错,大大降低了程序员的心智负担,易用性很好,不过在现在来看就有些尴尬了,而且因为我们常见字符大多在 Unicode 基本平面内,所以很多 Java 程序员误以为 char 就能表示一个字符,很多程序员连逐字符遍历字符串都不会,遇到 emoji 这样需要代理对表示的字符时就很容易出问题。


附遍历 Java 字符串的正确做法:

for(int offset = 0; offset < str.length();) {
  int ch = str.codePointAt(offset);
  // do something...
  offset += Character.charCount(ch);
}

本文来自:知乎

感谢作者:知乎

查看原文:Java 为什么使用 UTF-16 而不是更节省内存的 UTF-8?

51 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传