负字符值JAVA

负字符值JAVA,java,char,int,Java,Char,Int,为什么会发生以下情况: char p = 0; p--; System.out.println(p); 结果65535 为什么不给出编译错误或运行时异常? 我期待它,因为chars不能是负数。相反,它开始倒数。 提前感谢。因为Java语言就是这样定义的。运行时不会在每个操作中检查边界(可能是因为这会非常昂贵)。它只是溢出或下溢。因为Java语言就是这样定义的。运行时不会在每个操作中检查边界(可能是因为这会非常昂贵)。它只是溢出或下溢 为什么不给出编译错误或运行时异常 因为语言规范要求基元类型上

为什么会发生以下情况:

char p = 0;
p--;
System.out.println(p);
结果65535

为什么不给出编译错误或运行时异常? 我期待它,因为chars不能是负数。相反,它开始倒数。
提前感谢。

因为Java语言就是这样定义的。运行时不会在每个操作中检查边界(可能是因为这会非常昂贵)。它只是溢出或下溢。

因为Java语言就是这样定义的。运行时不会在每个操作中检查边界(可能是因为这会非常昂贵)。它只是溢出或下溢

为什么不给出编译错误或运行时异常

因为语言规范要求基元类型上的算术是模
2^width
,所以
-1
变成
2^16-1
作为
char

在这方面,有人指出

内置整数运算符不会以任何方式指示溢出或下溢

因此,禁止抛出异常

具体而言,对于使用的后缀减量运算符,其行为在中指定

否则,将从变量值中减去值1,并将差值存储回变量中。在减法之前,对值1和变量值执行二进制数字提升(§5.6.2)。如有必要,在存储变量之前,通过缩小原语转换(§5.1.3)缩小差异和/或对变量类型进行装箱转换(§5.1.7)。后缀减量表达式的值是存储新值之前的变量值

二进制数字提升将值和1转换为
int
(因为这里的类型是
char
),因此中间结果
-1
int
,然后执行缩小原语转换:

有符号整数到整数类型T的缩小转换只会丢弃n个最低阶位以外的所有位,其中n是用于表示类型T的位数。除了可能丢失有关数值大小的信息外,这可能导致结果值的符号与输入值的符号不同

导致
char
0xFFFF
(因为Java为其有符号整数类型指定了2的补码表示,在规范中明确说明):

对于整数值,求反与从零开始减法相同Java编程语言对整数使用两个补码表示,并且两个补码值的范围是不对称的,因此对最大负int或long的求反会产生相同的最大负数。在这种情况下会发生溢出,但不会引发异常。对于所有整数值x,-x等于(~x)+1

对于超出范围结果的一般环绕行为,例如:

如果整数乘法溢出,则结果是数学乘积的低阶位,如某些足够大的2的补码格式所示。因此,如果发生溢出,则结果的符号可能与两个操作数值的数学乘积的符号不同

类似的短语出现在整数加法的规范中,减法需要满足
a-b==a+(-b)
,因此溢出行为如下

为什么不给出编译错误或运行时异常

因为语言规范要求基元类型上的算术是模
2^width
,所以
-1
变成
2^16-1
作为
char

在这方面,有人指出

内置整数运算符不会以任何方式指示溢出或下溢

因此,禁止抛出异常

具体而言,对于使用的后缀减量运算符,其行为在中指定

否则,将从变量值中减去值1,并将差值存储回变量中。在减法之前,对值1和变量值执行二进制数字提升(§5.6.2)。如有必要,在存储变量之前,通过缩小原语转换(§5.1.3)缩小差异和/或对变量类型进行装箱转换(§5.1.7)。后缀减量表达式的值是存储新值之前的变量值

二进制数字提升将值和1转换为
int
(因为这里的类型是
char
),因此中间结果
-1
int
,然后执行缩小原语转换:

有符号整数到整数类型T的缩小转换只会丢弃n个最低阶位以外的所有位,其中n是用于表示类型T的位数。除了可能丢失有关数值大小的信息外,这可能导致结果值的符号与输入值的符号不同

导致
char
0xFFFF
(因为Java为其有符号整数类型指定了2的补码表示,在规范中明确说明):

对于整数值,求反与从零开始减法相同Java编程语言对整数使用两个补码表示,并且两个补码值的范围是不对称的,因此对最大负int或long的求反会产生相同的最大负数。在这种情况下会发生溢出,但不会引发异常。对于所有整数值x,-x等于(~x)+1

对于超出范围结果的一般环绕行为,例如:

如果是整数