Sing away sorrow, cast away care.
-Miguel de Cervantes (1547-1616),
Don Quixote (Lockhart's translation), Chapter viii
Casting conversion is applied to the operand of a cast operator (§15.15): the type of the operand expression must be converted to the type explicitly named by the cast operator. Casting contexts allow the use of an identity conversion (§5.1.1), a widening primitive conversion (§5.1.2), a narrowing primitive conversion (§5.1.3), a widening reference conversion (§5.1.4), or a narrowing reference conversion (§5.1.5). Thus casting conversions are more inclusive than assignment or method invocation conversions: a cast can do any permitted conversion other than a string conversion.
Some casts can be proven incorrect at compile time; such casts result in a compile-time error.
A value of a primitive type can be cast to another primitive type by identity conversion, if the types are the same, or by a widening primitive conversion or a narrowing primitive conversion.
A value of a primitive type cannot be cast to a reference type by casting conversion, nor can a value of a reference type be cast to a primitive type.
The remaining cases involve conversion between reference types. The detailed rules for compile-time correctness checking of a casting conversion of a value of compile-time reference type S (source) to a compile-time reference type T (target) are as follows:
final
class (§8.1.2), then the cast is always correct at compile time (because even if S does not implement T, a subclass of S might).
final
class (§8.1.2), then S must implement T, or a compile-time error occurs.
Object
, or a compile-time error occurs.
final
(§8.1.2), then the cast is always correct at compile time (because even if T does not implement S, a subclass of T might).
final
(§8.1.2), then T must implement S, or a compile-time error occurs.
[]
, that is, an array of components of type SC:
Object
, then a compile-time error occurs (because Object
is the only class type to which arrays can be assigned).
Cloneable
, the only interface implemented by arrays.
[]
, that is, an array of components of type TC, then a compile-time error occurs unless one of the following is true:
See §8 for the detailed specifications of classes, §9 for interfaces, and §10 for arrays.
If a cast to a reference type is not a compile-time error, there are two cases:
null
, then the cast is allowed. Otherwise, let R be the class of the object referred to by the run-time reference value, and let T be the type named in the cast operator. A cast conversion must check, at run time, that the class R is assignment compatible with the type T, using the algorithm specified in §5.2 but using the class R instead of the compile-time type S as specified there. (Note that R cannot be an interface when these rules are first applied for any given cast, but R may be an interface if the rules are applied recursively because the run-time reference value refers to an array whose element type is an interface type.) This modified algorithm is shown here:
Object
(§4.3.2, §20.1), or a run-time exception is thrown.
[]
-that is, an array of components of type RC:
Object
(§4.3.2, §20.1), or a run-time exception is thrown.
Cloneable
, the only interface implemented by arrays (this case could slip past the compile-time checking if, for example, a reference to an array were stored in a variable of type Object
).
[]
, that is, an array of components of type TC, then a run-time exception is thrown unless one of the following is true:
If a run-time exception is thrown, it is a ClassCastException
(§11.5.1.1,
§20.22).
Here are some examples of casting conversions of reference types, similar to the example in §5.2:
public class Point { int x, y; }
public interface Colorable { void setColor(int color); }
public class ColoredPoint extends Point implements Colorable { int color; public void setColor(int color) { this.color = color; } }
final class EndPoint extends Point { }
class Test { public static void main(String[] args) { Point p = new Point(); ColoredPoint cp = new ColoredPoint(); Colorable c;
// The following may cause errors at run time because // we cannot be sure they will succeed; this possibility // is suggested by the casts: cp = (ColoredPoint)p; // p might not reference an // object which is a ColoredPoint // or a subclass of ColoredPoint c = (Colorable)p; // p might not be Colorable
// The following are incorrect at compile time because // they can never succeed as explained in the text: Long l = (Long)p; // compile-time error #1 EndPoint e = new EndPoint(); c = (Colorable)e; // compile-time error #2
}
}
Here the first compile-time error occurs because the class types Long
and Point
are unrelated (that is, they are not the same, and neither is a subclass of the other),
so a cast between them will always fail.
The second compile-time error occurs because a variable of type EndPoint
can never reference a value that implements the interface Colorable
. This is because EndPoint
is a final
type, and a variable of a final
type always holds a value of the same run-time type as its compile-time type. Therefore, the run-time type of variable e
must be exactly the type EndPoint
, and type EndPoint
does not implement Colorable
.
Here is an example involving arrays (§10):
class Point { int x, y;
Point(int x, int y) { this.x = x; this.y = y; }
public String toString() { return "("+x+","+y+")"; }
}
public interface Colorable { void setColor(int color); }
public class ColoredPoint extends Point implements Colorable { int color; ColoredPoint(int x, int y, int color) { super(x, y); setColor(color); }
public void setColor(int color) { this.color = color; }
public String toString() { return super.toString() + "@" + color; }
}
class Test { public static void main(String[] args) { Point[] pa = new ColoredPoint[4]; pa[0] = new ColoredPoint(2, 2, 12); pa[1] = new ColoredPoint(4, 5, 24); ColoredPoint[] cpa = (ColoredPoint[])pa; System.out.print("cpa: {"); for (int i = 0; i < cpa.length; i++) System.out.print((i == 0 ? " " : ", ") + cpa[i]); System.out.println(" }"); }
}
This example compiles without errors and produces the output:
cpa: { (2,2)@12, (4,5)@24, null, null }
The following example uses casts to compile, but it throws exceptions at run time, because the types are incompatible:
public class Point { int x, y; }
public interface Colorable { void setColor(int color); }
public class ColoredPoint extends Point implements Colorable {
int color;
public void setColor(int color) { this.color = color; }
}
class Test { public static void main(String[] args) {
Point[] pa = new Point[100];
// The following line will throw a ClassCastException: ColoredPoint[] cpa = (ColoredPoint[])pa;
System.out.println(cpa[0]);
int[] shortvec = new int[2];
Object o = shortvec;
// The following line will throw a ClassCastException: Colorable c = (Colorable)o;
c.setColor(0);
}
}