Java内部字符串表示:它是UTF-16吗?

时间:2015-03-02 11:03:42

标签: java string utf-8

我在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匹配?

更新。有没有办法编写一个程序来打印字符串的内部字节

3 个答案:

答案 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位)字符数组。