最近我了解了在基础二系统中表示正整数和负整数的两种恭维方法。然后我尝试使用带有以下短代码的java来实现这一点:
int a=2147483647;
System.out.println("a: "+a);
System.out.println("a+1: "+(a+1));
short b=32767;
System.out.println("b: "+b);
System.out.println("b+1: "+(b+1));
哪个输出:
a:2147483647
a + 1:-2147483648
b:32767
b + 1:32768
这让我感到困惑,因为我认为b + 1,以二进制表示为011111111111111,将变为1000000000000000或十进制,-32768。发生了什么事?
答案 0 :(得分:11)
虽然b
是短的,但表达式(b + 1)
是一个int。右操作数是int,左操作数被提升为int,表达式是操作数的提升类型。
来自Java语言规范,5.6.2. Binary Numeric Promotion:
应用扩展基元转换(第5.1.2节)来转换以下规则指定的一个或两个操作数:
- 如果任一操作数的类型为double,则另一个操作数将转换为double。
- 否则,如果任一操作数的类型为float,则另一个操作数转换为float。
- 否则,如果任一操作数的类型为long,则另一个操作数将转换为long。
- 否则,两个操作数都将转换为int。
请注意,即使两个操作数都是短类型,也会发生上一次促销。您无法使用(b + (short) 1)
来避免升级为int。
来自15.18.2. Additive Operators (+ and -) for Numeric Types
数字操作数上的加法表达式的类型是其操作数的提升类型。
答案 1 :(得分:3)
执行+
会自动将short
提升为int
。这样做,你会看到溢出。
System.out.println("b+1: "+(short)(b+1)); //-32768
来自Java语言规范,5.6.2. Binary Numeric Promotion:
扩展基元转换(第5.1.2节)用于转换或 两个操作数由以下规则指定:
- 如果任一操作数的类型为double,则另一个操作数将转换为double。
- 否则,如果任一操作数的类型为float,则转换另一个操作数 漂浮。
- 否则,如果任一操作数的类型为long,则另一个操作数为 转换为长。
- 否则,两个操作数都将转换为int 。
注意最后一条规则,所以基本上这意味着即使它们都是短路,它们也会被提升为int,这是无法避免的。
你可以:short b= 32767;
short d= 12;
System.out.println("b+1: "+ (d+b)); // 32779
答案仍然有效。
答案 2 :(得分:3)
1
是一个int
字面值。在您计算b+1
时,您实际上将b
提升为int
,然后添加1
,从而产生32768
,这是完全合法的{{1}价值。如果再次将其转换为int
,您会看到您期望的溢出(short
):
-32768
答案 3 :(得分:2)
正如其他人所指出的那样,加法将操作数提升为int
。
请注意,+=
运算符会自动将转换回short
:
short b=32767;
System.out.println(b + 1); // 32768, because of integer promotion.
b += 1; // Equivalent to b = (short)(b + 1);
System.out.println(b); // -32768
b++;
/ ++b;
会产生与b += 1
相同的结果。
答案 4 :(得分:2)
不需要混淆,试试这个:
short b = 32767;
short c = b + 1;
你得到了什么?对,你得到:
错误:不兼容的类型:从int到short的可能有损转换 短c = b + 1;
那么,你的生产线会发生什么?
System.out.println("b+1: "+(b+1));
?
嗯,b+1
对于short
来说太大了,正如你说的那样,但是你在这里添加一个int,结果也是一个int。而32768是一个有效的int。
正如其他人已经指出的那样,如果你明确地将其强制转换为(short)
,你就能得到你所要求的。
另一方面,这对short c = b + 1;
不起作用,因为声明的类型是短的,而实际的类型是int
。
short c = (short) (b + 1);
解决了“问题”