我在SO上发现,Java字符串在内部表示为UTF-16。出于好奇,我开发并运行了以下代码片段(Java 7):
public class StringExperiment {
public static void main(String...args) throws UnsupportedEncodingException {
System.out.println(Arrays.toString("ABC".getBytes()));
}
}
导致:
[65, 66, 67]
正在打印到控制台输出。
它如何与UTF-16匹配?
更新。有没有办法编写一个程序来打印字符串的内部字节?
答案 0 :(得分:3)
你似乎误解了一些事情。
对于所有系统关注,以及开发人员关心的大部分时间,char
s也可以是载体鸽,以及String
所述载体鸽的序列。虽然是,但在内部,字符串是char
s的序列(更准确地说是UTF-16代码单元),这不是这里的问题。
您不会将char
写入文件,也不会从文件中读取char
。你编写并读取字节。
为了将字节序列读取为字符/载体鸽子序列,您需要解码器;类似地(这就是你在这里做的),为了将字符/载体鸽子变成字节,你需要一个编码器。在Java中,这两个都可以从Charset
获得。
String.getBytes()
恰好使用带有默认平台字符编码的编码器(使用Charset.defaultCharset()
获得),并且对于您的输入字符串"ABC"
和您的JRE实现,会发生这样的序列生成的字节数是65,66,67。因此结果。
现在,试试String.getBytes(Charset.forName("UTF-32LE"))
,你会得到不同的结果。
答案 1 :(得分:3)
Java的内部字符串表示基于他们的char
,因此是UTF-16。
Unless it isn't:现代VM(自Java 6 Update 21性能发布以来)可能会尝试使用基本的ASCII(单字节编码)来节省空间。
序列化/ java-native-interface是在modified CESU-8(UTF-8的代理无关变体)编码中完成的,NUL表示为两个字节以避免嵌入的零。
所有这些都与您的测试无关[&34;虽然:
You are asking Java to encode the string in the platform's default-charset,而且那不是内部字符集:
public byte[] getBytes()
使用平台的默认字符集将此String编码为字节序列,将结果存储到新的字节数组中。
未指定此字符串无法在默认字符集中进行编码时此方法的行为。当需要更多地控制编码过程时,应该使用CharsetEncoder类。
答案 2 :(得分:1)
Java Strings确实在内部表示为UTF-16,但是您调用的是getBytes
方法,它执行following(我的重点)
public byte[] getBytes()
使用平台将此String编码为字节序列 默认字符集,将结果存储到新的字节数组中。
您平台的默认编码可能不是UTF-16。
如果您使用允许您指定编码的变体,您可以看到字符串在其他编码中的外观:
public byte[] getBytes(Charset charset)
如果查看java.lang.String
的{{3}},可以看到String内部存储为(16位)字符数组。