Normally, integer literals are always interpreted as int - the reason that it works in a line where you declare and initialize a byte is because that statement is treated as a special case by the Java compiler.
The reason why Java does not allow this with a method that takes a byte is because it can lead to confusing situations. For example:
To avoid all these potential problems, Java simply does not automatically convert values to a byte.
Note also that the byte declaration and initialization only works when you initialize the byte with a compile-time constant. This, for example, doesn't work:
Campbell Ritchie wrote:If you have declaration and initialisation on the same line, the compiler will work out that the literal (7) is in the correct range and take that as a byte value. That only works if you use one line.
And how come that for widening conversion it works.. that's quite confusing.. if the reason of forbidding the narrowing implicit conversion was for the clarity's sake. Why would it work for the widening implicit conversion? I understand that even though passing Integer.MAX_VALUE to a "getFloat(float f)" it will always work so it's not risky.. however it's not coherent with the overall clarity of the implicit conversion. At least this is my humble view on it.
There is explanation in JLS ( 5.3. Method Invocation Conversion) :
Method invocation conversions specifically do not include the implicit narrowing of integer constants which is part of assignment conversion (§5.2). The designers of the Java programming language felt that including these implicit narrowing conversions would add additional complexity to the overloaded method matching resolution process (§15.12.2).
Thus, the program:
causes a compile-time error because the integer literals 12 and 2 have type int, so neither method m matches under the rules of (§15.12.2). A language that included implicit narrowing of integer constants would need additional rules to resolve cases like this example.