In your first example, sh1
is final
, and has a value which can be determined at compile time to be "castrated down" to a byte
. In effect, it's a constant. If you remove the final
, it won't compile anymore.
In your second example, it cannot be determined by the compiler that your method argument is "safe", you have to do an explicit cast, as other answers mentioned.
For the nitty gritty details, see here (JLS references and all). But a simple example:
final byte b1 = 127;
final byte b2 = 1;
final byte b = b1 + b2; // <-- FAIL: 128 greater than Byte.MAX_VALUE
final byte b1 = 12;
final byte b2 = 3;
final byte b = b1 + b2; // <-- SUCCESS: 15 fits