我对Java字符串的编码存在困惑。我有几个问题,请帮助我:
1)Java字符串在内存中的本地编码是什么?当我写String a = "Hello"
时,以哪种格式存储?由于Java是机器独立的,系统不会进行编码。
2)我在网上读到“UTF-16”是默认编码,但我感到困惑,因为当我写int a = 'c'
时,我得到的是ASCII表中字符的编号。那么ASCII和UTF-16是相同的吗?
3)此外,我不确定字符串在内存中的存储取决于什么:操作系统,语言?
我对Java字符串的编码存在困惑。我有几个问题,请帮助我:
1)Java字符串在内存中的本地编码是什么?当我写String a = "Hello"
时,以哪种格式存储?由于Java是机器独立的,系统不会进行编码。
2)我在网上读到“UTF-16”是默认编码,但我感到困惑,因为当我写int a = 'c'
时,我得到的是ASCII表中字符的编号。那么ASCII和UTF-16是相同的吗?
3)此外,我不确定字符串在内存中的存储取决于什么:操作系统,语言?
Java内部将字符串存储为UTF-16编码。
“默认编码”并不完全正确。Java内部将字符串存储为UTF-16编码,但外部使用的编码——“系统默认编码”——因平台而异,有些平台甚至可以通过环境变量进行修改。
ASCII是Latin 1的子集,而Latin 1又是Unicode的子集。UTF-16是一种对Unicode进行编码的方式。因此,如果你对ASCII范围内的任何字符执行int i='x'
测试,你将得到ASCII值。但是,UTF-16可以表示比ASCII更多的字符。
Java 2平台在char数组以及String和StringBuffer类中使用UTF-16编码。
因此,作为Java 2平台的一部分,这些类使用UTF-16编码。
char
数据类型表示一个UTF-16代码单元(而不是字符,即Unicode代码点),因此我认为可以非常肯定地说,Java语言对文本的表示是UTF-16。是的,理论上实现可能会选择在底层执行不同的操作,但最终它们必须使其看起来就像在使用UTF-16一样。 - Laurence Gonsalves1) 字符串是对象,通常包含一个 char
数组和字符串的长度。字符数组通常实现为一组连续的16位字,每个字节按本地字节顺序包含Unicode字符。
2) 将字符值分配给整数会将16位Unicode字符代码转换为其整数等效项。因此,'c'
,它的Unicode编码是 U+0063,变成了 0x0063
,即99。
3) 因为每个String
都是一个对象,所以它包含其他信息,而不仅仅是类成员(例如,类描述符单词、锁/信号量单词等)。
补充说明
对象内容取决于JVM实现(它确定与每个对象相关联的固有开销),以及类的实际编码方式(即,某些库可能比其他库更有效)。
例子
典型的实现将为每个对象实例分配两个词的开销(用于类描述符/指针和信号量/锁控制词);一个String
对象还包含一个int
长度和一个char[]
数组引用。字符串的实际字符内容存储在第二个对象中,即char[]
数组,该数组又分配了两个字,加上一个数组长度字,再加上为字符串需要的多少个16位char
元素(加上创建字符串时遗留下来的任何额外字符)。
补充说明2
一个字符表示一个Unicode字符的情况只在大多数情况下成立。这将意味着 UCS-2 编码和 2005 年之前为真。但是到现在 Unicode 已经变得更大了,而字符串必须使用 UTF-16 编码--在其中一个 Java 字符串中,一个 Unicode 字符可能要使用两个char
。
看看Apache实现的实际源代码,例如:
http://www.docjar.com/html/api/java/lang/String.java.html
javac -encoding ISO-8859-1
选项创建.class
文件,那么所有源文件的内容不是存储在UTF-8中,而是存储在ISO-8859-1中吗? - parsecer编辑:感谢LoadMaster帮助我纠正答案 :)
1)所有内部字符串处理都是使用UTF-16。
2)ASCII是UTF-16的子集。
3)在Java内部,使用的是UTF-16。对于其他情况,取决于你所处的位置。
char[]
的形式存储,每个元素包含一个16位UTF-16 Unicode字符。UTF-8不用于在内部存储字符串,但用于将I/O流转换为字符串和从字符串转换。 - David R TribbleString
类型一直使用内部的 char[]
数组来存储其字符值。 - David R Tribble