Why does the compiler not give an error for this addition operation?

This question already has an answer here:

  • Why don't Java's +=, -=, *=, /= compound assignment operators require casting? 11 answers

  • The answer is provided by JLS 15.26.2:

    For example, the following code is correct:

    short x = 3;

    x += 4.6;

    and results in x having the value 7 because it is equivalent to:

    short x = 3;

    x = (short)(x + 4.6);

    So, as you can see, the latest case actually work because the addition assignment (as any other operator assignment) performs an implicit cast to the left hand type (and in your case a is a byte ). Extending, it is equivalent to byte e = (byte)(a + b); , which will compile happily.


    While decompiling your code will explain what Java is doing, the reason why it's doing it can be generally found in the language specification. But before we go into that, we have to establish a few important concepts:

  • A literal numeral is always interepreted as an int .

    An integer literal is of type long if it is suffixed with an ASCII letter L or l (ell); otherwise it is of type int (§4.2.1).

  • A byte can only hold an integer value between -128 and 127, inclusive.

  • An attempt to assign a literal that is larger than the type that can hold it will result in a compilation error. This is the first scenario you're encountering.

  • So we're back to this scenario: why would adding two bytes that are clearly more than what a byte can handle not produce a compilation error?

    It won't raise a run-time exception because of overflow.

    This is the scenario in which two numbers added together suddenly produce a very small number. Due to the small size of byte 's range, it's extremely easy to overflow; for example, adding 1 to 127 would do it, resulting in -128.

    The chief reason it's going to wrap around is due to the way Java handles primitive value conversion; in this case, we're talking about a narrowing conversion. That is to say, even though the sum produced is larger than byte , the narrowing conversion will cause information to be discarded to allow the data to fit into a byte , as this conversion never causes a run-time exception.

    To break down your scenario step by step:

  • Java adds a = 127 and b = 5 together to produce 132.
  • Java understands that a and b are of type byte , so the result must also be of type byte .
  • The integer result of this is still 132, but at this point, Java will perform a cast to narrow the result to within a byte - effectively giving you (byte)(a += b) .
  • Now, both a and z contain the result -124 due to the wrap-around.

  • I came to the conclusion that the result of an expression that involves variables cannot be guaranteed. The resulting value can be within or outside the byte range so compiler throws off an error.

    No, that's not the reason. The compilers of a staticly-typed language work in this way: Any variable must be declared and typed, so even if its value is not known at compile-time, its type is known. The same goes for implicit constants. Based upon this fact, the rules to compute scales are basically these:

  • Any variable must have the same or higher scale than the expression at its right side.
  • Any expression has the same scale of the maximum term involved on it.
  • An explicit cast forces, of corse, the scale of the right-side expression.
  • (These are in fact a simplified view; actually might be a little more complex).

    Apply it to your cases:

    byte d = 1 + b
    

    The actual scales are:

    byte = int + byte
    

    ... (because 1 is considered as an implicit int constant). So, applying the first rule, the variable must have at least int scale.

    And in this case:

    byte z = (a+=b);
    

    The actual scales are:

    byte = byte += byte
    

    ... which is OK.

    Update

    Then, why byte e = a + b produce a compile-time error?

    As I said, the actual type rules in java are more complex: While the general rules apply to all types, the primitive byte and short types are more restricted: The compiler assumes that adding/substracting two or more bytes/shorts is risking to cause an overflow (as @Makoto stated), so it requires to be stored as the next type in scale considered "safer": an int .

    链接地址: http://www.djcxy.com/p/12782.html

    上一篇: 将int加到short

    下一篇: 为什么编译器不为这个加法操作提供一个错误?