The JLS (§5.2) has special rules for assignment conversion with constant expressions:
In addition, if the expression is a constant expression (§15.28) of type
byte,short,char, orint:
- A narrowing primitive conversion may be used if the type of the variable is
byte,short, orchar, and the value of the constant expression is representable in the type of the variable.
If we follow the link above, we see these in the definition of constant expression:
- Literals of primitive type and literals of type
String- The additive operators
+and-- Simple names (§6.5.6.1) that refer to constant variables (§4.12.4).
If we follow the second link above, we see that
A variable of primitive type or type
String, that isfinaland initialized with a compile-time constant expression (§15.28), is called a constant variable.
It follows that foo + foo can only be assigned to fooFoo if foo is a constant variable. To apply that to your cases:
-
byte foo = 1;does not define a constant variable because it’s notfinal. -
final byte foo = 1;does define a constant variable, because it’sfinaland initialized with a constant expression (a primitive literal). -
final byte foo = fooArray[0];does not define a constant variable because it’s not initialized with a constant expression.
Note that whether fooFoo is itself final doesn’t matter.