[英]Weird behaviour of byte in java
我有以下代码:
public class First
{
public static void main(String[] args)
{
byte b=50;
byte c=b*2; //Error
byte d=50*2; //d=100
byte e=(byte)258; //e=258%256;
byte f=(byte)128; //f=128%256;
}
}
byte
算术表达式都将首先提升为int
,然后再执行。 因此,我期望d=50*2
也会报告错误,因为50*2
的结果是一个int
值,我们将其存储在一个byte
而没有任何显式类型转换。 如果Java隐式进行强制转换,为什么c=b*2
报告错误? byte
变量范围内的值,则必须显式地将其强制转换为byte
并且将要存储的值是模256(字节大小)的值。 因此,为什么byte f=(byte)128
返回-128
? 由于128 % 256 = 128
,所以我期望的是f=128
,但它返回-128
。 为什么? 非常感谢。
这是因为50*2;
将在编译时解析,而b*2;
将在运行时解决。 因此,在编译时Java编译器确保结果为50*2;
将为100。但是在b*2;
情况下b*2;
,正如您还提到的,算术运算的结果为int
,并且编译器无法确定结果是否可以超出byte
限制,因此它抱怨并希望您通过强制转换或更改类型来确保结果。
您可以使用javap -v Test.class
进行验证。 见下文:
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: bipush 100
2: istore_1
3: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
6: iload_1
7: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
10: return
LineNumberTable:
line 4: 0
line 5: 3
line 6: 10
对于第二个问题,@ Eran已经使用128和258的位表示进行了解释,您可以从JLS§5.1.3进一步阅读。 缩小原始转换
将有符号整数缩小为整数类型T会简单地丢弃除n个最低阶位以外的所有位,其中n是用于表示类型T的位数。除了可能丢失有关数值幅度的信息外, ,这可能导致结果值的符号与输入值的符号不同。
至于第二个问题,当您向下转换数字类型时,将使用输入的低位来初始化输出。
因此,其二进制表示形式为0......010000000
的int
128
变为字节10000000
(取低8位),即-128
。
另一方面, 258
是0........01000000010
,当您采用低8位时,您将得到00000010
,即2。
除分配外,还有其他可能发生某些类型转换的地方:即在表达式中。
要了解原因,请考虑以下内容。 在表达式中,中间值所需的精度有时会超出两个操作数的范围。
例如,检查以下表达式:
byte a = 40;
byte b = 50;
byte c = 100;
int d = a * b / c;
中间项a * b
很容易超出其任一字节操作数的范围。 为了处理此类问题,Java在评估表达式时会自动将每个byte
, short
或char
操作数提升为int
。
这意味着子表达式a*b
是使用整数而不是字节执行的。 因此,即使a和b都指定为类型字节,中间表达式50 * 40的结果2,000也合法。
与自动升级一样有用,它们可能导致令人困惑的编译时错误。
例如,以下看似正确的代码会导致问题:
byte b = 50;
b = b * 2; // Error! Cannot assign an int to a byte!
该代码正在尝试将50 * 2(一个完全有效的byte
值)存储回byte
变量中。 但是,由于在评估表达式时将操作数自动提升为int
,因此结果也提升为int
。 因此,表达的结果现在类型是int
,其不能被分配给一个byte
而无需使用的cast
。
即使在这种特殊情况下,即使分配的值仍然适合目标类型,也是如此。 如果您了解溢出的后果,则应使用显式强制转换,例如
byte b = 50;
b = (byte)(b * 2);
得出正确的值100。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.