Why during autoboxing final long to Byte compilation error happens, but final int to Byte is ok?
Asked Answered
F

1

15

There is no error during auto-boxing of constants with int and short types to Byte, but constant with long type do has error. Why?

final int i = 3;
Byte b = i; // no error

final short s = 3;
Byte b = s; // no error


final long l = 3;
Byte b = l; // error
Flowered answered 13/9, 2017 at 20:26 Comment(0)
S
16

From JLS Sec 5.2, "Assignment contexts" (emphasis mine):

In addition, if the expression is a constant expression (§15.28) of type byte, short, char, or int:

  • A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable.

  • A narrowing primitive conversion followed by a boxing conversion may be used if the type of the variable is:

    • Byte and the value of the constant expression is representable in the type byte.
    • ...

It's simply not allowed for longs by the spec.

Note that the second bullet point here says that this happens irrespective of the boxing: assigning a constant long expression to a byte variable would similarly fail:

// Both compiler errors.
byte primitive = 0L;
Byte wrapped = 0L;
Salford answered 13/9, 2017 at 20:34 Comment(7)
I am curious to learn why. Could it be related to the fact that long is to machine words?Beauty
Probably mostly because int is the default type for constant values, including expressions, so there will be a lot of code like short s = 123 and if such a narrowing conversion weren't used, you'd need casts everywhere. In particular, Java has no syntax for literals of narrower the types. On the other hand, if the type of the expression is explicitly long, because L has been used on a constant or some part is constant, then it may be an error to narrow it, and this situation is much less common than the int case and I guess the balance falls in favor making it an error.Acaricide
Note also that the autoboxing really doesn't have much to do with this: the same thing applies to purely primitive types. The rules were just extended to include assignment to boxed types when they were added. @JonathanRosenneAcaricide
@Acaricide " the autoboxing really doesn't have much to do with this" Indeed: I had a comment along those lines in an earlier version of my answer. However, I removed it, because the section I quote does actually explicitly describe narrowing followed by boxing; so I removed my mention of this point and included the extra quote instead.Salford
I think the error makes sense because a byte can only hold values between -128..127, and a narrowing cast from a long (which is used for storing much larger values) would usually be a programming error.Snakebird
@MickMnemonic the same argument doesn't apply to an int, though: that can represent values outside that range. The compiler only allows it for int if the constant value is in a range representable by byte. There's no (obvious) reason why you couldn't do the same with long.Salford
There may be a parallel with the JVM type system, which doesn't distinguish between int and smaller types in the constant pool, "local variables" (registers) and the stack machine stack. But if that's the actual reason I'd say the language designers were led astray by a leaky abstraction.Windproof

© 2022 - 2024 — McMap. All rights reserved.