This has less† to do with whether or not 3 + 8
is evaluated to 11
at compile-time, and more to do with the fact the compiler is explicitly permitted to implicitly narrow int
s to byte
s in certain cases. In particular, the language specification explicitly permits implicit narrowing conversions to byte
of constant expressions of type int
that can fit in a byte
at compile-time.
The relevant section of the JLS here is section §5.2:
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.
The compile-time narrowing of constants means that code such as:
byte theAnswer = 42;
is allowed. Without the narrowing, the fact that the integer literal 42
has type int
would
mean that a cast to byte
would be required:
†: Obviously, as per the specification, the constant expression needs to be evaluated to see if it fits in the narrower type or not. But the salient point is that without this section of the specification, the compiler would not be permitted to make the implicit narrowing conversion.
Let's be clear here:
byte a = 3;
byte b = 8;
The reason that these are permitted is because of the above section of the specification. That is, the compiler is allowed to make the implicit narrowing conversion of the literal 3
to a byte
. It's not because the compiler evaluates the constant expression 3
to its value 3
at compile-time.