5.11 Reference Casting and the instanceof Operator
In this section we explore type casting of references and the instanceof operator that can be used to perform either type comparison or pattern matching.
The Cast Operator
The basic form of the type cast expression for reference types has the following syntax:
(
destination_type
)
reference_expression
where the reference expression evaluates to a reference value of an object of some reference type. A type cast expression checks that the reference value refers to an object whose type is compatible with the destination type, meaning that its type is a subtype of the destination type. The construct (destination_type) is usually called the cast operator. The result of a type cast expression for references is always a reference value of an object. The literal null can be cast to any reference type.
The code below illustrates the various scenarios that arise when using the cast operator. In this discussion, it is the type cast expression that is important, not the evaluation of the assignment operator in the declaration statements. At (1), the cast is from the superclass Object to the subclass String; the code compiles and at runtime this cast is permitted, as the reference obj will denote an object of class String. At (2), the cast is from the superclass Object to the subclass Integer; the code compiles, but at runtime this cast results in a ClassCastException, since the reference obj will denote an object of class String, which cannot be converted to an Integer. At (3), the cast is from the class String to the class Integer. As these two classes are unrelated, the compiler flags an error for the cast.
Object obj = new String(“Cast me!”);
String str = (String) obj; // (1) Cast from Object to String.
Integer iRef1 = (Integer) obj; // (2) Cast from Object to Integer, but
// ClassCastException at runtime.
Integer iRef2 = (Integer) str; // (3) Compile-time error!
// Cast between unrelated types.
The following conversions can be applied to the operand of a cast operator:
- Both widening and narrowing reference conversions, followed optionally by an unchecked conversion (§11.2, p. 575)
- Both boxing and unboxing conversions
Boxing and unboxing conversions that can occur during casting are illustrated by the following code. Again, it is the type cast expression that is important in this discussion, rather than whether the assignment operator requires one in the declaration statements.
// (1) Boxing and casting: Number <– Integer <– int:
Number num = (Number) 100;
// (2) Casting, boxing, casting: Object <– Integer <– int <– double:
Object obj = (Object) (int) 10.5;
// (3) Casting, unboxing, casting: double <— int <– Integer <– Object:
double d = (double) (Integer) obj;
Note that the resulting object at (1) and (2) is an Integer, but the resulting value at (3) is a double. The boxing conversions from int to Integer at (1) and (2) are implicit, and the unboxing conversion from Integer to int at (3) is also implicit.
Casting to a supertype is always permitted, but redundant, since a supertype reference can always refer to an object of its subtype.
Leave a Reply