The Java 8 JLS also states in §5.6.1:
5.6.1. Unary Numeric Promotion
Some operators apply unary numeric promotion to a single operand, which must produce a value of a numeric type:
...
- Otherwise, if the operand is of compile-time type
byte
, short
, or char
, it is promoted to a value of type int
by a widening primitive conversion (§5.1.2).
...
Thus, if we take the following expression:
int i = ...
short s = (short) i << 2;
Will result in a compiler error:
Main.java:4: error: incompatible types: possible lossy conversion from int to short
short s = (short) i << 2;
Ideone demo
This is due to the fact that the cast binds to the first argument of the shift, not the whole expression. Here is the whole expression with explicit parenthesis:
short s = ((byte) i) << 2;
Whereas
int i = ...;
int j = (short) i << 2;
Will successfully compile.
Ideone demo
So the effective bits to use for anything < int
is the same as for int
(5
bits) since they are upcasted to int
automatically.
If you cast the result of the whole expression to, e.g. short
(short s = (short) (i << 2)
, then there is no automatism that takes place in the compiler. But Bohemian's answer gives a logical bound as to what bits of the right hand operator will effectively influence the value after the cast.
In newer JLS versions, the section has been reworded. For example, in Java 14 JLS, §5.6 we find (the section is shortened for breviety, I recommend reading the whole paragraph to get the full context):
5.6. Numeric Contexts
Numeric contexts apply to the operands of arithmetic operators, array creation and access expressions, conditional expressions, and the result expressions of switch expressions.
An expression appears in a numeric arithmetic context if the expression is one of the following:
...
- An operand of a shift operator
<<
, >>
, or >>>
(§15.19). Operands of these shift operators are treated separately rather than as a group. A long
shift distance (right operand) does not promote the value being shifted (left operand) to long
.
...
Numeric promotion determines the promoted type of all the expressions in a numeric context. The promoted type is chosen such that each expression can be converted to the promoted type, and, in the case of an arithmetic operation, the operation is defined for values of the promoted type. The order of expressions in a numeric context is not significant for numeric promotion. The rules are as follows:
...
Next, widening primitive conversion (§5.1.2) and narrowing primitive conversion (§5.1.3) are applied to some expressions, according to the following rules:
...
Otherwise, none of the expressions are of type double
, float
, or long
. In this case, the kind of context determines how the promoted type is chosen.
In a numeric arithmetic context or a numeric array context, the promoted type is int
, and any expressions that are not of type int undergo widening primitive conversion to int
.
In a numeric choice context, the following rules apply:
...
- Otherwise, the promoted type is
int
, and all the expressions that are not of type int
undergo widening primitive conversion to int
.
...