Conversions of numeric types to narrower types can result in lost or misinterpreted data if the value of the wider type is outside the range of values of the narrower type. Consequently, all narrowing conversions must be guaranteed safe by range-checking the value before conversion.
Narrowing primitive conversions are allowed in cases where the value of the wider type is within the range of the narrower type.
The following table presents the rules for narrowing primitive conversions of integer types. In the table, for an integer type
n represents the number of bits used to represent the resulting type
Possible Resulting Errors
Lost or misinterpreted data
Magnitude error; negative number even though
When integers are cast to narrower data types, the magnitude of the numeric value and the corresponding sign can be affected. Consequently, data can be lost or misinterpreted.
Floating-Point to Integer Conversion
Floating-point conversion to an integral type
T is a two-step procedure:
1. When converting a floating-point value to an
long and the value is a
NaN, a zero value is produced. Otherwise, if the value is not infinity, it is rounded toward zero to an integer value
Vcan be represented as a
Vcan be represented as an
int, then the
- The value is negative infinity or a value too negative to be represented, and
- The value is positive infinity or a value too positive to be represented, and
short, the result of the conversion is the result of a narrowing conversion to type
T of the result of the first step
Narrower primitive types can be cast to wider types without affecting the magnitude of numeric values (see the JLS, §5.1.2, Widening Primitive Conversion" [JLS 2005]), for more information). Conversion from
float or from
double can lead to loss of precision (loss of least significant bits). No runtime exception occurs despite this loss.
Note that conversions from
double or from
float can also lose information about the overall magnitude of the converted value (see NUM53-J. Use the strictfp modifier for floating-point calculation consistency across platforms for additional information).
Noncompliant Code Example (Integer Narrowing)
In this noncompliant code example, a value of type
int is converted to a value of type
byte without range checking:
The resulting value may be unexpected because the initial value (128) is outside of the range of the resulting type.
Compliant Solution (Integer Narrowing)
This compliant solution validates that the value stored in the wider integer type is within the range of the narrower type before converting to the narrower type. It throws an
ArithmeticException if the value is out of range.
workWith() method can explicitly narrow when the programmer's intent is to truncate the value:
Range-checking is unnecessary because the truncation that is normally implicit in a narrowing conversion is made explicit. The compiler will optimize the operation away, and for that reason, no performance penalty is incurred. Similar operations may be used for converting to other integral types.
Noncompliant Code Example (Floating-Point to Integer Conversion)
The narrowing primitive conversions in this noncompliant code example suffer from loss in the magnitude of the numeric value as well as a loss of precision:
The minimum and maximum
float values are converted to minimum and maximum
int values (
0x7fffffff respectively). The resulting
short values are the lower 16 bits of these values (
0xffff). The resulting final values (0 and −1) might be unexpected.
Compliant Solution (Floating-Point to Integer Conversion)
This compliant solution range-checks both the
j variables before converting to the resulting integer type. Because both values are out of the valid range for a
short, this code will always throw an
Noncompliant Code Example (
The narrowing primitive conversions in this noncompliant code example suffer from a loss in the magnitude of the numeric value as well as a loss of precision. Because
Double.MAX_VALUE is larger than
c receives the value
infinity, and because
Double.MIN_VALUE is smaller than
b receives the value
Compliant Solution (
This compliant solution performs range checks on both
j before proceeding with the conversions. Because both values are out of the valid range for a
float, this code will always throw an
Casting a numeric value to a narrower type can result in information loss related to the sign and magnitude of the numeric value. As a result, data can be misrepresented or interpreted incorrectly.
Automated detection of narrowing conversions on integral types is straightforward. Determining whether such conversions correctly reflect the intent of the programmer is infeasible in the general case. Heuristic warnings could be useful.
Numeric Conversion Errors [FLC]
|||NUM12-J. Ensure conversions of numeric types to narrower types do not result in lost or misinterpreted data LiveLesson|