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);
}
}