Widening and Narrowing Conversions

This section provides more details on when a cast is needed, and also introduces the terminology of type conversions. This is explained in terms of an assignment between one variable and another, and exactly the same rules apply in the transfer of values from actual parameters to formal parameters.

When you assign an expression to a variable, a conversion must be done. Conversions among the primitive types are either identity, widening, or narrowing conversions.

  • Identity conversions are an assignment between two identical types, like an int to int assignment. The conversion is trivial: just copy the bits unchanged.

  • Widening conversions occur when you assign from a less capacious type (such as a short) to a more capacious one (such as a long). You may lose some digits of precision when you convert either way between an integer type and a floating point type. An example of this appeared in the previous section with a long-to-float assignment. Widening conversions preserve the approximate magnitude of the result, even if it cannot be represented exactly in the new type.

  • Narrowing conversions are the remaining conversions. These are assignments from one type to a different type with a smaller range. They may lose the magnitude information. Magnitude means the largeness of a number, as in the phrase “order of magnitude.” So a conversion from a long to a byte will lose information about the millions and billions, but will preserve the least significant digits.

Widening conversions are inserted automatically by the compiler. Narrowing conversions always require an explicit cast.

Expressions are evaluated in one of the canonical types (int, long, float or double). That means if your expression is assigned to a non-canonical type (byte, short, or char), an identity or a narrowing conversion will be required. If a narrowing conversion is required, you must write a cast. The cast tells the compiler, “OK, I am aware that the most significant digits are being lost here. Just go ahead and do it.” Now it should be clear why we have to use a cast in:

byte loNibble = (byte) (byteMe & 0x0F);

Each operand in the expression “byteMe & 0xOF” is promoted to int, then the “and” operation is done yielding a 32-bit int result. The variable receiving the expression is an 8-bit byte, so a narrowing conversion is required. Hence, the cast “(byte)” is applied to the entire right-hand side result to mollify the compiler.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.114.28