【问题标题】:What is the character encoding of String in Java?Java中String的字符编码是什么?
【发布时间】:2010-12-15 18:00:36
【问题描述】:

我实际上对 Java 中的字符串编码感到困惑。我有一些问题。如果你知道他们的答案,请帮助我:

1) Java 字符串在内存中的原生编码是什么?当我写String a = "Hello" 时,它将以哪种格式存储?由于 Java 是独立于机器的,我认为系统不会进行编码。

2) 我在网上看到“UTF-16”是默认编码,但我很困惑,因为当我写 int a = 'c' 时,我得到了 ASCII 表中的字符编号。那么 ASCII 和 UTF-16 是一样的吗?

3) 我也不确定内存中字符串的存储取决于:操作系统、语言?

【问题讨论】:

标签: java string character-encoding


【解决方案1】:
  1. Java 在内部将字符串存储为 UTF-16。

  2. “默认编码”不太正确。 Java 在内部将字符串存储为 UTF-16,但在外部使用的编码,即“系统默认编码”,因平台而异,甚至可以通过某些平台上的环境变量等内容进行更改。

    ASCII 是拉丁语 1 的子集,拉丁语 1 是 Unicode 的子集。 UTF-16 是一种编码 Unicode 的方式。因此,如果您对 ASCII 范围内的任何字符执行 int i = 'x' 测试,您将获得 ASCII 值。然而,UTF-16 可以表示比 ASCII 更多的字符。

  3. 来自java.lang.Character docs:

    Java 2 平台在 char 数组以及 String 和 StringBuffer 类中使用 UTF-16 表示。

    因此它被定义为 Java 2 平台的一部分,UTF-16 用于这些类。

【讨论】:

  • char 和 char 数组的使用仅针对 String 和 StringBuffer 的公共、外部 API 定义。字符的内部存储是特定于实现的。
  • @jarnbjo 以上是来自文档的直接引用。 Java 中的 char 数据类型代表一个 UTF-16 代码单元(不是字符,也就是 Unicode 代码点),所以我认为可以肯定地说 Java 语言的文本表示是 UTF-16。是的,可以想象一个实现可以选择在幕后做一些不同的事情,但最终他们必须让它看起来就像他们使用的是 UTF-16。
  • 由于无法访问 String 和 StringBuffer 类的内部存储,因此假设您引用的语句适用于它是有意义的。
  • UTF-16BE 还是 UTF-16LE ?
  • @HendyIrawan Jana 不允许您访问单个字节,只能访问字符(对应于 UTF-16 代码单元),因此没有设置字节序。内存中使用的实际字节序取决于 JVM/平台,就像用于在内存中存储 int 的字节序一样。
【解决方案2】:

虽然这不能回答您的问题,但值得注意的是……在 java 字节码(类文件)中,字符串以 UTF-8 格式存储。 http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html

【讨论】:

  • @Loadmaster 我相信这是一个有用的信息,我明确提到它是类文件 - 那么你的问题是什么?
  • 但它没有回答这个问题。您可以将其作为评论发布并以“虽然这不能回答您的问题,但值得注意的是......”这确实是一条有用的信息,但我不知道他们使用了 UTF- 8.重点是什么?这意味着 JVM 必须在启动时将每个字符串转换为 UTF-16。
  • @Sergey Tachenov:字符串以 UTF-8 格式存储,因此 .class 文件更小(平均而言)。
  • 当你把它们放在你通常做的 JAR 文件中时,这根本不重要。 UTF-16 的压缩效率几乎提高一倍。
  • @parsecer:Oracel 的文档对这个“encoding : Set the source file encoding name, such as EUC-JP and UTF-8”相当严格——所以这只是源文件(*.java ) 编码,*.class文件中Strings的编码保持UTF-8
【解决方案3】:

1) 字符串是对象,通常包含char 数组和字符串的长度。字符数组通常实现为 16 位字的连续数组,每个字都包含一个按本机字节顺序排列的 Unicode 字符。

2) 将字符值分配给整数会将 16 位 Unicode 字符代码转换为其等效的整数。因此,'c',即 U+0063,变为0x0063,即 99。

3) 由于每个String 都是一个对象,它包含除其类成员之外的其他信息(例如,类描述符字、锁/信号量字等)。

附录
对象内容取决于 JVM 实现(它决定了与每个对象相关的固有开销),以及类的实际编码方式(即,某些库可能比其他库更有效)。

示例
一个典型的实现将为每个对象实例分配两个字的开销(用于类描述符/指针,以及一个信号量/锁控制字); String 对象还包含 int 长度和 char[] 数组引用。字符串的实际字符内容存储在第二个对象 char[] 数组中,该数组又分配了两个字,加上一个数组长度字,加上字符串所需的尽可能多的 16 位 char 元素(加上创建字符串时留下的任何额外字符)。

附录 2
one char 表示 one Unicode 字符的情况仅在大多数情况下为真。这意味着UCS-2 编码在 2005 年之前为真。但现在 Unicode 已经变得更大,字符串必须使用 UTF-16 进行编码——可惜单个 Unicode 字符可能使用 two char s 在 Java 中 String。

查看 Apache 实现的实际源代码,例如在:
http://www.docjar.com/html/api/java/lang/String.java.html

【讨论】:

  • 实际上你打算在你的 3) 部分中说什么。它包含其他信息,所以.... ??
  • “将字符值分配给整数会将 16 位 Unicode 字符代码转换为其等效整数。”这里有点令人困惑的是,Unicode 编码与前 256 个字符的 ASCII 一致。 Unicode 与前 256 个字符的扩展 ASCII(8 位)相关;反过来,扩展 ASCII 与前 128 位的 7 位 ASCII 直接对应。因此,“c”在 Unicode、扩展 ASCII 和 ASCII 中编码为 0x63。这就是为什么你会看到 'c' 的 int 并认为它是 ASCII(它是 :)。
  • @HawkeyeParker:是的,7 位 ASCII (ISO 646) 和 8 位 ISO 8859-1 (Latin-1) 是 Unicode 的真子集。话虽如此,Java 将所有字符值编码为 16 位 Unicode。
  • 绝对。我只是为那些可能对重叠感到困惑的人澄清一下。
【解决方案4】:

编辑:感谢 LoadMaster 帮助我更正我的答案:)

1) 所有内部字符串处理均以 UTF-16 进行。

2) ASCII 是 UTF-16 的子集。

3) Java 内部是 UTF-16。其余的,这取决于你在哪里,是的。

【讨论】:

  • 字符串在内部(内存中)存储为char[],每个元素包含一个 16 位 UTF-16 Unicode 字符。 UTF-8 不用于内部存储字符串,而是用于将 I/O 流转换为字符串。
  • @LoadMaster:它在一段时间内发生了变化吗? Java 内部总是使用 UTF-16 吗?
  • 是的,String 一直使用内部的char[] 来存储其字符值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-16
  • 2013-07-06
相关资源
最近更新 更多