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. As a result, all narrowing conversions must be guaranteed safe by range-checking the value before conversion.
...
Code Block | ||
---|---|---|
| ||
class CastAway {
public static void workWith(int i) {
// check if i is within byte range
if ((i < Byte.MIN_VALUE) || (i > Byte.MAX_VALUE)) {
throw new ArithmeticException("Value is out of range");
}
byte b = (byte) i;
// work with b
}
}
|
The following code example demonstrates how to perform explicit narrowing from a long
to an int
where range-checking is not required.
Code Block | ||
---|---|---|
| ||
long value = /* initialize */; int i = (int) (value % 0x100000000L); // 2^32 |
The 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)
...
Code Block | ||
---|---|---|
| ||
double i = Double.MIN_VALUE; double j = Double.MAX_VALUE; if ((i < Float.MIN_VALUE) || (i > Float.MAX_VALUE) || (j < Float.MIN_VALUE) || (j > Float.MAX_VALUE)) { throw new ArithmeticException ("Value is out of range"); } float b = (float) i; float c = (float) j; // other operations |
Exceptions
NUM12-EX0: Java's narrowing conversions are both well defined and portable. The effects of narrowing on integral types can be easily reproduced in code; however, the effects of narrowing on floating-point types and between floating-point types and integral types cannot be easily represented. Knowledgeable programmers may intentionally apply narrowing conversions involving floating-point types in contexts where their output is both expected and reasonable. Consequently, narrowing conversions are permitted when the code contains comments that document both the use of narrowing conversions and the anticipated truncation. A suitable comment might read:
// Deliberate narrowing cast of i; possible truncation OK
This exception does not permit narrowing conversions without range-checking among integral types. The following code example demonstrates how to perform explicit narrowing from a long
to an int
where range-checking is not required.
Code Block | ||
---|---|---|
| ||
long value = /* initialize */;
int i = (int) (value % 0x100000000L); // 2^32
|
The 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.
Risk Assessment
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.
...