Type Conversion


Every Java expression has a type which can be determined upon examination of the types of the variables and constants in it. In certain cases, however, the type of an expression may not be what the surrounding context expects. For example, passing the expression 3 + 4 to System.out.println is just such a case. The type of the expression 3 + 4 is int but System.out.println expects a String. In cases such as this a type conversion is needed.

Type Promotion

In the aforementioned example System.out.println(3 + 4), the expression 3 + 4 is evaluated to 7 and then converted automatically, at runtime, to a String value which is what println expects. This automatic conversion is a somewhat special case of type promotion.

Type promotion is an automatic type conversion from a “lesser” base type to a “greater” one or from any type to String via the toString() method.

A promotion from on base type to another may occur in an arithmetic expression:

1
2
double x = 3.14 + 10; /* 10 is promoted to a double */
double y = 12; /* 12 is promoted to a double then assigned */

As mentioned earlier, type promotion occurs from a “lesser” type to a “greater” one where a type is “less” than another if it offers smaller precision. In our previous example, an int offers less precision than a double thus an int value can be promoted to a double as necessary. For the same reason a double cannot be promoted to an int. If an double is used where an int is expected, Java will generate an error:

1
int z = 2.4; Compile-time error: possible loss of precision

Type Casting

As we saw in the previous examples, type conversion occurs automatically in the form of type promotion in certain cases. We also saw an example where the type conversion would not occur automatically. In such cases it is possible to force the conversion via a type cast. A type cast may mean loss of precision, but the compiler will perform the conversion and will not generate an error:

1
int z = (int) 2.4; // Cast the double 2.4 to int; loss of precision: z = 2

It is also possible to cast objects from one type to another. When casting an object to a parent type, the cast will always succeed and never generate an error. For example, an instance of any class can be cast to Object:

1
2
3
4
class Foo {
}
Foo f = new Foo();
Object o = (Object) f; // cast f to parent type Object - always successful

When casting an object to a non-parent type, a runtime check will be performed and if the cast fails, an exception will be raised:

1
2
3
4
5
6
7
class Foo {
}
Foo f = new Foo();
Object o = (Object) f; // cast f to parent type Object - always successful
f = (Foo) o; // o is actually a Foo object so the cast is successful
o = new Object();
f = (Foo) o; //this time o cannot be cast to Foo; generates ClassCastException