繁体   English   中英

Java中字节的奇怪行为

[英]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;
    }
}
  1. 我知道任何涉及byte算术表达式都将首先提升为int ,然后再执行。 因此,我期望d=50*2也会报告错误,因为50*2的结果是一个int值,我们将其存储在一个byte而没有任何显式类型转换。 如果Java隐式进行强制转换,为什么c=b*2报告错误?
  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......010000000int 128变为字节10000000 (取低8位),即-128

另一方面, 2580........01000000010 ,当您采用低8位时,您将得到00000010 ,即2。

Java中的自动类型提升

除分配外,还有其他可能发生某些类型转换的地方:即在表达式中。

要了解原因,请考虑以下内容。 在表达式中,中间值所需的精度有时会超出两个操作数的范围。

例如,检查以下表达式:

byte a = 40;
byte b = 50;
byte c = 100;
int d = a * b / c;

中间项a * b很容易超出其任一字节操作数的范围。 为了处理此类问题,Java在评估表达式时会自动将每个byteshortchar操作数提升为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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM