Understand primitive ranges, arithmetic promotion, floating-point precision, boxing, and narrowing conversions.
Answer: Both use 16-bit value sets, compared with int's signed 32-bit range. Short ranges from -32,768 through 32,767; char ranges from 0 through 65,535. Every short and char value fits exactly in int.
Char and short have different signedness, so neither range contains the other. Storage width alone does not determine whether a conversion between them is widening.
Answer: No. Many arithmetic operations apply numeric promotion, so adding two byte, short, or char operands produces int. But comparisons produce boolean, and casts, increment expressions, conditional expressions, and other operations have their own rules.
Explain promotion for the specific operator rather than applying one blanket result-type rule to all expressions. Mixing a larger numeric type can also change the arithmetic result type.
Answer: The addition produces int, so use an explicit narrowing conversion when intended: byte result = (byte) (left + right);. Casting only one operand to byte does not stop arithmetic promotion.
If overflow must be rejected, first compute the sum as int and check it against Byte.MIN_VALUE and Byte.MAX_VALUE. A cast alone silently keeps the low eight bits.
Answer: For an ordinary finite value within range, it rounds toward zero, so (int) 100.001f is 100 and (int) -3.9f is -3. It does not round to the nearest integer.
NaN converts to zero, while out-of-range values and infinities are clamped to the int endpoints. These rules differ from simply discarding high-order bits in integral narrowing.
Answer: Yes. Int-to-double is a widening primitive conversion, and double can represent every int value exactly. No cast is needed, for example double value = 13;.
This exactness does not extend to every long value. Double's 53 bits of significand precision cannot represent all signed 64-bit integers exactly.
Answer: For primitive double, widening is implicit: double value = 100L;. Precision can be lost for large long values even though the conversion is classified as widening.
Double is a wrapper reference type. Double boxed = (double) 100L; explicitly converts to double and then boxes. Double boxed = 100L; is not valid: ordinary assignment does not combine arbitrary primitive widening followed by boxing.
Answer: Yes, but some int values lose precision. Float has only 24 bits of significand precision. For example, 16,777,217 rounds to 16,777,216 when converted to float.
"Widening" describes a language conversion category, not a guarantee that every source value is represented exactly. Use an appropriate representation when exact integer identity matters.
Answer: Use an f or F suffix, such as float value = 498.47F;. An unsuffixed floating-point literal is double, so assigning it to float normally requires an explicit cast.
The suffix states the intended literal type directly. A cast from a double expression is a separate narrowing operation and can round, overflow to infinity, or underflow, depending on the value.
Answer: The first int constant fits byte's signed range and qualifies for assignment narrowing. The second is outside that range, so implicit narrowing is rejected.
byte value = (byte) 128; compiles but stores -128. This demonstrates why a compiling cast is not evidence that the original numeric value was preserved.
Answer: No. Integral-to-integral narrowing retains the target's low-order bits. Floating-to-integral conversion first follows rounding and range rules; conversions to byte, short, or char then include further integral narrowing. Double-to-float follows floating-point rounding rules.
public class NumericNarrowing {
public static void main(String[] args) {
System.out.println((byte) 128);
System.out.println((int) -3.9);
System.out.println((int) Double.NaN);
System.out.println((int) Double.POSITIVE_INFINITY);
int original = 16_777_217;
float rounded = original;
System.out.println((int) rounded);
}
}
The output is -128, -3, 0, 2147483647, and 16777216. Choose the conversion rule for the source and target types rather than applying an integral-bit explanation to floating-point values.
References: JLS: numeric conversions and promotion and JLS: operators and expressions.