Java char 是有符号的还是无符号的?

Is Java char signed or unsigned for arithmetic?

Java char是一个16位的数据类型,但是在对其进行运算时,它是有符号的还是无符号的?

你可以在算术中将它用作无符号的 16 位整数吗?

例如,以下是正确的吗?

char c1;
char c2;

int i = c1 << 16 | c2;

或者是否需要先去除 c2 的符号扩展位?

(我确信这个问题的答案在别处,但明显的搜索似乎没有找到)。

来自specs

For char, from '\u0000' to '\uffff' inclusive, that is, from 0 to 65535

因为它是 16 位,这意味着它们是无符号的。

char 是无符号的。来自 JLS§4.2.1:

For char, from '\u0000' to '\uffff' inclusive, that is, from 0 to 65535

...但请注意,当您对它们使用任何 various mathematic operations 时(包括按位运算和移位运算),它们会根据其他操作数的类型扩展为另一种类型,并且其他类型可能已签名:

  1. Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:

    • If either operand is of type double, the other is converted to double.

    • Otherwise, if either operand is of type float, the other is converted to float.

    • Otherwise, if either operand is of type long, the other is converted to long.

    • Otherwise, both operands are converted to type int.

例如,char + charint,所以:

public class Example {
    public static void main(String[] args) {
        char a = 1;
        char b = 2;

        char c = a + b;          // error: incompatible types: possible lossy conversion from int to char
        System.out.println(c);
    }
}

重新位扩展,如果我们按照the link above来加宽原语转换:

A widening conversion of a char to an integral type T zero-extends the representation of the char value to fill the wider format.

所以 char 0xFFFF 变成 int 0x0000FFFF,而不是 0xFFFFFFFF。