We often have to convert a data value of one type to another type, or mix data types within one expression.
If one converts a data value from one type to another that moves one from left to right in the list of types below, the conversion is called a widening conversion.
Widening conversions do not lose information about the overall magnitude of a numeric value. Indeed, conversions widening from an integral type to another integral type and from float
to double
do not lose any information at all; the numeric value is preserved exactly.
Conversion of an int
or a long
value to float
, or of a long
value to double
, may however, result in loss of precision, since floating-point types store their values in an inherently approximate way, while integral types store their values exactly.
If one converts a data value from one type to another in the reverse direction (right to left in the list above), the conversion is called a narrowing conversion.
Additionally, converting a long
, float
, or double
type to a char
type, and converting a char
type to either a byte
or short
type, are also considered narrowing conversions.
Narrowing conversions may lose information about the overall magnitude of a numeric value and may also lose precision.
Types can be converted in three ways: implicitly by promotion, implicitly by assignment, and explicitly by casting.
Promotion occurs automatically in binary operations involving two operands of different types, and can happen in several ways:
The presence of one double promotes the other operand to a double
2D / 3 // 3 is treated as the double 3.0 1F + 6.72 // 1F is treated as the double 1.0
The presence of a float in the absence of a double promotes the other operand to a float
2.4F * 3 // 3 is treated as the float 3F 5L - 1.7F // 5 is treated as the float 5F
The presence of a long in the absence of a double or float promotes the other operand to a long
3L + 2 // 2 is treated as the long 2L 16 % 2L // 16 is treated as the long 16L
In the absence of doubles, floats, or longs, both operands are converted to the int type.
2 * 3 //both 2 and 3 are treated as type int.
Type conversion can also occur when a value of one type is assigned to a variable of another type.
Note, only widening conversions are allowed by assignment, as seen by the following examples:
double d = 100; //this is a widening conversion, no problem
int n = 5.0; //5.0 is a double, so this is a narrowing
//conversion. This creates a compiler error
int j = 2 + 6 / 3.0; //The presence of the "3.0" converts
//(by promotion) the 6 to a double.
//The quotient is then a double, which
//converts (by promotion) the 2 to a
//double. This gives a sum which is
//a double, which makes the assignment
//to j a narrowing conversion. Hence,
//this too creates a compiler error.
To perform a narrowing conversion, we simply place the desired type in parentheses before the expression to be converted, in the following way:
(type) expression
Example:
(int) 5.0 //converts 5.0 to an int type
This "desired type in parentheses" is called a "cast operator". Be careful about the order of precedence for the cast operator. Casts happen after increments, decrements, and unary negatives, but before just about every other operator. This means the cast in the example below affects only the value of 5 and not the quotient :
double h = (double) 5 / 2; //Note: h = 2.5
Casting without paying attention to the range of the data type can cause unexpected problems. Consider the following:
byte b = (byte) 500000; //Here, b = 32 as //500000 % 128 = 32 //Recall the size of a //byte and the fact that //128 = 2^7