这个循环将无限期地继续:
char a = 100;
for(a=100; a>=0;--a)
System.out.println(a);
是否会发生这种情况,因为a被提升为算术运算的int值,并从16位char值扩展到32位,因此将始终保持正值?
它确实会无限循环 – 你说的理由很接近.这是因为a不能表示任何不满足> = 0的数字 – char是无符号的.算术下溢在Java中是明确定义的,并且没有指示.请参阅规范的以下相关部分.
> §4.2.2
The integer operators do not indicate overflow or underflow in any way.
这意味着除了比较值之外没有溢出/下溢的迹象……例如,如果a< = - a,则表示发生了下溢.
> §15.15.2
Before the subtraction,binary numeric promotion (§5.6.2) is performed on the value 1 and the value of the variable. If necessary,the difference is narrowed by a narrowing primitive conversion (§5.1.3) and/or subjected to boxing conversion (§5.1.7) to the type of the variable before it is stored. The value of the prefix decrement expression is the value of the variable after the new value is stored.
因此,我们可以看到这里有两个主要步骤:二进制数字促销,然后是缩小的初始转换.
> §5.6.2
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
.
我们可以看到递减表达式使用被视为int的方式,从而执行扩展转换.这允许它表示值-1.
> §5.1.3
A narrowing primitive conversion may lose information about the overall magnitude of a numeric value and may also lose precision and range.
…
A narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits,where n is the number of bits used to represent type T. In addition to a possible loss of information about the magnitude of the numeric value,this may cause the sign of the resulting value to differ from the sign of the input value.
仅保留n个最低阶位意味着仅保留int表达式a-1的最低16位.由于-1为0b22222111 22222111 22222111 22222111,因此仅保存较低的0b22222111 22222111.由于char是无符号的,所有这些位都对结果有贡献,给出65535.
注意到这里有什么?从本质上讲,这意味着Java整数算法是模块化的;在这种情况下,模数是2 ^ 16或65536,因为char是16位数据类型. -1(mod 65536)≡65535,因此减量将回绕.