In java,
There are integral types(char
/short
/int
/long
/byte
)
There are floating types(float
/double
)
There is boolean type(boolean
), not integral type, unlike C language.
Questions:
Is there a generic rule for casting(as per JLS) that talks, which type can be converted to another type? Out of common sense, I know that, integral and floating types casting to
boolean
is not allowedPlease help me understand the reasons for below output:
/* * Casting rules for primitive types */ double aDoubleValue = 30000000000000000000.123438934; int doubleToInt = (int)aDoubleValue; //stores max value 2147483647, makes sense!! byte doubleToByte = (byte)aDoubleValue; //stores -1, why not 127? short doubleToShort = (short)aDoubleValue; // stores -1, why not 32767? long doubleToLong = (long)aDoubleValue; // stores 9223372036854775807, makes sense!! float doubleToFloat = (float)aDoubleValue; // stores 3.0E19, 3.0 x 10^19 max value of float char doubleToChar = (char)aDoubleValue; // what does this store?
The JLS lists
Note the missing conversions from
byte
andshort
tochar
, even thoughchar
is two bytes long.Everything else needs an explicit cast. Narrowing is a little more complex:
double
tofloat
uses standard IEEE 754 rounding.(byte)0xfff == (byte)-1
;long
, the value is converted by rounding towards zero.long
, the value is first converted toint
by rounding towards zero. Then the resultingint
is converted to the target type using integer conversion.Examples:
yields
Integer.MAX_VALUE
as per rounding rules.first converts to
int
, yieldingInteger.MAX_VALUE
and then converts that tobyte
.Integer.MAX_VALUE
is0x7fffffff
, hence the byte value0xff
which is-1
.same again: converts to
int
, yieldingInteger.MAX_VALUE
.0x7fffffff
toshort
yields0xffff
, i.e.-1
.The tricky thing is actually the to-
char
conversion.char
is a single, 16-bit unicode character, hencechar doubleToChar = (char)aDoubleValue
gives you'\uffff'
by the now familiar rules.As can be seen there is a difference between floating point and integer narrowing operations. The floating point operations do actual rounding, while the integer operations perform bitwise clamping.
The integer semantics are probably inherited from C. At least the first step of the float-to-integral narrowing ops are also what you expected. The second narrowing steps, from double/float to short, byte and char may seem a little surprising, but if you really cast float to short, you should probably double check that you know what you are doing anyway.