Java char数组是否始终是有效的UTF-16(Big Endian)编码?

假设我将Java字符数组( char[] )实例编码为字节:

  • 为每个字符使用两个字节
  • 使用大端编码(在最左边的最左边存储最高8位,在最右边的字节存储最不重要的8位)

这总是会创建一个有效的UTF-16BE编码吗? 如果不是,哪些代码点将导致无效编码?


这个问题与关于Java char类型的 这个问题以及关于Java字符串的内部表示的这个问题非常相关。

不可以。您可以创建包含任何16位值的char实例 – 没有任何东西可以将它们限制为有效的UTF-16代码单元,也不会将它们的数组限制为有效的UTF-16序列。 Even String不要求其数据是有效的UTF-16:

 char data[] = {'\uD800', 'b', 'c'}; // Unpaired lead surrogate String str = new String(data); 

有效的UTF-16数据的要求在Unicode标准的第3章中列出(基本上,所有内容都必须是Unicode标量值,并且所有代理必须正确配对)。 您可以测试char数组是否是有效的UTF-16序列,并使用CharsetEncoder将其转换为UTF-16BE(或LE)字节CharsetEncoder

 CharsetEncoder encoder = Charset.forName("UTF-16BE").newEncoder(); ByteBuffer bytes = encoder.encode(CharBuffer.wrap(data)); // throws MalformedInputException 

(如果你有字节,也可以使用CharsetDecoder 。)