简体   繁体   English

Java中字节的奇怪行为

[英]Weird behaviour of byte in java

I have this code: 我有以下代码:

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. I know that any arithmetic expression involving byte is first promoted to int and then it is performed. 我知道任何涉及byte算术表达式都将首先提升为int ,然后再执行。 Therefore I expected d=50*2 to also report an error, because the result of 50*2 is an int value and we are storing it in a byte without any explicit type cast. 因此,我期望d=50*2也会报告错误,因为50*2的结果是一个int值,我们将其存储在一个byte而没有任何显式类型转换。 If Java does the casting implicitly, why does c=b*2 report an error? 如果Java隐式进行强制转换,为什么c=b*2报告错误?
  2. I know that if I want to store a value which is not within the range of a byte variable,then I have to explicitly type cast it into byte and the value that will be stored is the value modulo 256 (Size of byte). 我知道,如果要存储不在byte变量范围内的值,则必须显式地将其强制转换为byte并且将要存储的值是模256(字节大小)的值。 Therefore, why does byte f=(byte)128 return -128 ? 因此,为什么byte f=(byte)128返回-128 Since 128 % 256 = 128 , so what I expect is f=128 , but it returns -128 . 由于128 % 256 = 128 ,所以我期望的是f=128 ,但它返回-128 Why? 为什么?

Thanks a lot. 非常感谢。

This is because 50*2; 这是因为50*2; will be resolved at compile time while b*2; 将在编译时解析,而b*2; will be resolved at runtime. 将在运行时解决。 So, at compile time Java compiler is sure that result of 50*2; 因此,在编译时Java编译器确保结果为50*2; will be 100. But in case of b*2; 将为100。但是在b*2;情况下b*2; , as you have also mentioned that result of arithmetic operation is int , and compiler cannot be sure if result could exceed byte limits, so it complains and wants you to make sure the things by casting or changing type. ,正如您还提到的,算术运算的结果为int ,并且编译器无法确定结果是否可以超出byte限制,因此它抱怨并希望您通过强制转换或更改类型来确保结果。

You can use javap -v Test.class to verify the same. 您可以使用javap -v Test.class进行验证。 See below: 见下文:

 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

For your second question, @Eran has already explained using bit representation of 128 and 258, and you can read further from JLS §5.1.3. 对于第二个问题,@ Eran已经使用128和258的位表示进行了解释,您可以从JLS§5.1.3进一步阅读 Narrowing Primitive Conversion 缩小原始转换

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. 将有符号整数缩小为整数类型T会简单地丢弃除n个最低阶位以外的所有位,其中n是用于表示类型T的位数。除了可能丢失有关数值幅度的信息外, ,这可能导致结果值的符号与输入值的符号不同。

As for your second question, when you downcast a numeric type, the low bits of the input are used to initialize the output. 至于第二个问题,当您向下转换数字类型时,将使用输入的低位来初始化输出。

Therefore, the int 128 , whose binary representation is 0......010000000 becomes the byte 10000000 (you take the low 8 bits), which is -128 . 因此,其二进制表示形式为0......010000000int 128变为字节10000000 (取低8位),即-128

On the other hand, 258 is 0........01000000010 , and when you take the low 8 bits you get 00000010 , which is 2. 另一方面, 2580........01000000010 ,当您采用低8位时,您将得到00000010 ,即2。

Automatic Type Promotions in Java Java中的自动类型提升

In addition to assignments, there is another place where certain type conversions may occur: ie in expressions. 除分配外,还有其他可能发生某些类型转换的地方:即在表达式中。

To see why, consider the following. 要了解原因,请考虑以下内容。 In an expression, the precision required of an intermediate value will sometimes exceed the range of either operand. 在表达式中,中间值所需的精度有时会超出两个操作数的范围。

For example, examine the following expression: 例如,检查以下表达式:

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

The result of the intermediate term a * b easily exceeds the range of either of its byte operands. 中间项a * b很容易超出其任一字节操作数的范围。 To handle this kind of problem, Java automatically promotes each byte , short or char operand to int when evaluating an expression. 为了处理此类问题,Java在评估表达式时会自动将每个byteshortchar操作数提升为int

This means that the subexpression a*b is performed using integers—not bytes. 这意味着子表达式a*b是使用整数而不是字节执行的。 Thus, 2,000, the result of the intermediate expression, 50 * 40, is legal even though a and b are both specified as type byte. 因此,即使a和b都指定为类型字节,中间表达式50 * 40的结果2,000也合法。

As useful as the automatic promotions are, they can cause confusing compile-time errors. 与自动升级一样有用,它们可能导致令人困惑的编译时错误。

For example, this seemingly correct code causes a problem: 例如,以下看似正确的代码会导致问题:

byte b = 50;
b = b * 2; // Error! Cannot assign an int to a byte!

The code is attempting to store 50 * 2, a perfectly valid byte value, back into a byte variable. 该代码正在尝试将50 * 2(一个完全有效的byte值)存储回byte变量中。 However, because the operands were automatically promoted to int when the expression was evaluated, the result has also been promoted to int . 但是,由于在评估表达式时将操作数自动提升为int ,因此结果也提升为int Thus, the result of the expression is now of type int , which cannot be assigned to a byte without the use of a cast . 因此,表达的结果现在类型是int ,其不能被分配给一个byte而无需使用的cast

This is true even if, as in this particular case, the value being assigned would still fit in the target type. 即使在这种特殊情况下,即使分配的值仍然适合目标类型,也是如此。 In cases where you understand the consequences of overflow, you should use an explicit cast, such as 如果您了解溢出的后果,则应使用显式强制转换,例如

byte b = 50;
b = (byte)(b * 2);

which yields the correct value of 100. 得出正确的值100。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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