A widening conversion changes a primitive value to a broader type, usually without an explicit cast. Java performs it implicitly in arithmetic, assignments, returns, argument passing, and unary plus. Although the value is usually preserved, widening can change character literals into integer codes, propagate negative byte bits, or round large integers. section 2.5 section 4.6
Watch for these narrowly scoped failure modes:
- Unary plus widens a char to int. A duplicated plus in string concatenation can turn a quotation mark into code 34, producing output such as `User not found: 34User"` instead of the intended message. section 2.5
- Widening a negative byte sign-extends it. In bitwise composition, `-1` becomes `0xFFFFFFFF`, so an unmasked low byte can corrupt the entire result. section 4.13
- Widening can lose precision when converting `int` or `long` to `float`, or `long` to `double`. At sufficiently large values, distinct integers round to the same floating-point number. section 4.6
Preventing unintended widening
Prefer a one-character string over a character literal when concatenating punctuation, and use formatting calls when suitable. Mask bytes before bitwise composition: `((hi & 0xFF) << 8) | (lo & 0xFF)`. Avoid `float` unless justified, make intended floating-point widening explicit with a cast, and use `BigDecimal` when controlled precision matters. section 2.5 section 4.13 section 4.6
String error(String userName) {
return "User not found: " +
+ '"' + userName + '"';
}
Inspect the duplicated-plus concatenation that applies unary plus to a quotation-mark character. section 2.5
int readTwoBytes() {
byte lo = readLowByte();
byte hi = readHighByte();
return (hi << 8) | lo;
}
Compare unmasked byte composition with the sign-extension hazard described above. section 4.13
long longVal = 1L << 53; double doubleVal = longVal; double doubleValPlusOne = longVal + 1; System.out.println(doubleVal == doubleValPlusOne); #1
Observe two distinct long values becoming equal after widening to double. section 4.6
