Next: Object types. Up: Primitive types. Previous: The character type.


Type conversions

Textbook: Section 9.5

Implicit conversion

We've already seen that Java will automatically convert an int to a double when needed. For example, if you type ``9.0 / 5,'' Java automatically converts 5 into a double before doing the division.

In general, Java will happily assume you meant to do a conversion whenever it considers the new type to be ``broader'' (i.e., less restrictive) than the old type. Java observes the following hierarchy of types.

 byte
  |
short    char
    \   /
     int        narrow
      |           |
     long         V
      |         broad
    float
      |
    double
The following example illustrate.
int i = 'A';     // OK: Sets i to 65, the Unicode value of 'A'
float f = 3;     // OK: Even though 3 is an int literal, f holds 3.0
long k = 2.0;    // ERROR: 2.0 is a double, broader than a long.
int j = 5L;      // ERROR: 5 is a long, broader than an int.
These types of conversions are called numeric promotions.

The same rules apply in parameter passing. There's no problem with passing an int argument into a method that takes a double parameter - Java will simply automatically convert it.

And the same rules apply with arithmetic, except that Java doesn't include the concept of byte or short arithmetic. So if you add two byte values, they'll get promoted into ints before the addition takes place.

Explicit conversion

So what do you do in those cases where you want to convert down the hierarchy? For example, if I have a double value, how can I convert it into an int value? Java requires you to explicitly mark these conversions, so that you don't accidentally lose information. (When you convert down the hierarchy, there's a risk of problems, since the value may not be a valid value for the new type. For example, though 200 is a perfectly good int value, it's not good as an byte value.)

You do these explicit conversions using the casting operator. It's a unary operator that you can place in an expression; you type the name of the type ot which you want to convert in parentheses. For example:

int j = (int) IO.readDouble();
This reads a floating-point number from the user, but then it applies the casting operator to convert the return value of IO.readDouble() into an int. When you convert a floating-point value to an integer type, any fractional value is dropped, so anything the user types after the decimal point is lost here.

The casting operator is very high in the hierarchy of operators - it ranks above the multiplication level, on the same level as unary negation.

int i = 1, j = 2;
double x = (double) i / j;
In the above code, the casting operator only applies to i - converting the value 1 into 1.0. Because one side of the division is a double value, the other side is implicitly converted before the division takes place, so that you get 0.5 as a result.

Say you wanted to print a random integer between 1 and 6. The following accomplishes it.

IO.println((int) (6.0 * Math.random() + 1));
Here the parentheses around ``6.0 * Math.random() + 1'' were important, as otherwise the casting operator would apply only to the 6.0, and the effect would be lost when it is immediately (implicitly) converted to a double again so that it can be multiplied by the double value returned by Math.random(). As it is, the random number between 0.0 and 1.0 returned by Math.random() is multiplied by 6, giving a random double between 0.0 and 6.0. We add 1 to it, moving the range to being between 1.0 and 7.0. We typecast this to an int; any fractional part is lost, and the result will be an integer between 1 and 6.


Next: Object types. Up: Primitive types. Previous: The character type.