Java: String中每个字符的大小

Java: Size of each character in a String

我在网上的各个地方都读到 Java 在内部使用 UTF-16 来表示 String 对象。这意味着 String 中的每个字符占用两个字节。然而,对于以下代码,我们发现每个字符在字符串中可能占用可变数量的字节。

public class ChracterSize {

    public static void main(String[] args) {
        String s = "\u0061\u024E\u2013\u65E5";
        System.out.println(s + " " + s.getBytes().length);

        System.out.println("\u0061" + " " + "\u0061".getBytes().length);
        System.out.println("\u024E" + " " + "\u024E".getBytes().length);
        System.out.println("\u2013" + " " + "\u2013".getBytes().length);
        System.out.println("\u65E5" + " " + "\u65E5".getBytes().length);

    }

}

以上程序的输出是:

aɎ–日 9
a 1
Ɏ 2
– 3
日 3

每个字符对应的代码点是:

a : \u0061
Ɏ : \u024E
– : \u2013
日 : \u65E5

对此行为的解释是什么?

我必须将可能包含非罗马字符的文本存储到数据库中的固定字节长度字段中。我是否应该假设我应该分配四倍的文本长度以确保安全?

UTF-16 并不意味着每个字符都编码为 2 个字节。

https://en.wikipedia.org/wiki/UTF-16

UTF-16 (16-bit Unicode Transformation Format) is a character encoding capable of encoding all 1,112,064 possible characters in Unicode. The encoding is variable-length, as code points are encoded with one or two 16-bit code units. (also see Comparison of Unicode encodings for a comparison of UTF-8, -16 & -32)

UTF-16 developed from an earlier fixed-width 16-bit encoding known as UCS-2 (for 2-byte Universal Character Set) once it became clear that a fixed-width 2-byte encoding could not encode enough characters to be truly universal.

方法getBytes() 不会为您提供字符串中存储的字节数。相反,它为您提供了以特定编码表示此字符串的字节,在本例中为默认编码,可能是 UTF-8。

在内部,该字符串包含一个 char 类型的数组,并且该类型每个项目恰好包含两个字节。但是,一些补充字符可能由两个数组条目表示,因此它们实际上可能在字符串中占用 4 个字节。