Casting Conversion

5.5 Casting Conversion

Casting conversion is applied to the operand of a cast operator (§15.16): the type of the operand expression must be converted to the type explicitly named by the cast operator.

Casting contexts allow the use of one of: • an identity conversion (§5.1.1) • a widening primitive conversion (§5.1.2) • a narrowing primitive conversion (§5.1.3) • a widening and narrowing primitive conversion (§5.1.4)

CONVERSIONS AND PROMOTIONS Casting Conversion 5.5

• a widening reference conversion (§5.1.5) optionally followed by either an unboxing conversion (§5.1.8) or an unchecked conversion (§5.1.9)

• a narrowing reference conversion (§5.1.6) optionally followed by either an unboxing conversion (§5.1.8) or an unchecked conversion (§5.1.9)

• a boxing conversion (§5.1.7) optionally followed by a widening reference conversion (§5.1.5)

• an unboxing conversion (§5.1.8) optionally followed by a widening primitive conversion (§5.1.2).

Value set conversion (§5.1.13) is applied after the type conversion. The compile-time legality of a casting conversion is as follows: • An expression of a primitive type may undergo casting conversion to another

primitive type, by an identity conversion (if the types are the same), or by a widening primitive conversion, or by a narrowing primitive conversion, or by a widening and narrowing primitive conversion.

• An expression of a primitive type may undergo casting conversion to a reference type without error, by boxing conversion.

• An expression of a reference type may undergo casting conversion to a primitive type without error, by unboxing conversion.

• An expression of a reference type may undergo casting conversion to another reference type if no compile-time error occurs given the rules in §5.5.1.

The following tables enumerate which conversions are used in certain casting conversions. Each conversion is signified by a symbol:

• - signifies no casting conversion allowed • ≈ signifies identity conversion (§5.1.1) • ω signifies widening primitive conversion (§5.1.2) • η signifies narrowing primitive conversion (§5.1.3) • ωη signifies widening and narrowing primitive conversion (§5.1.4) • ⇑ signifies widening reference conversion (§5.1.5) • ⇓ signifies narrowing reference conversion (§5.1.6) • ⊡ signifies boxing conversion (§5.1.7) • ⊔ signifies unboxing conversion (§5.1.8)

5.5 Casting Conversion CONVERSIONS AND PROMOTIONS

In the tables, a comma between symbols indicates that a casting conversion uses one conversion followed by another. The type Object means any reference type other than the eight wrapper classes Boolean , Byte , Short , Character , Integer , Long , Float , Double .

Table 5.1. Casting conversions to primitive types

To → byte

float double boolean From ↓ byte

ω ω - short

ω ω - char

ω ω - int

ω ω - long

ω ω - float

≈ ω - double

η ≈ - boolean

- - ≈ Byte

⊔,ω ⊔,ω - Short

⊔,ω ⊔,ω - Character

⊔,ω ⊔,ω - Integer

⊔,ω ⊔,ω - Long

⊔,ω ⊔,ω - Float

⊔ ⊔,ω - Double

- ⊔ - Boolean

- - ⊔ Object

CONVERSIONS AND PROMOTIONS Reference Type Casting 5.5.1

Table 5.2. Casting conversions to reference types

To →

Byte Short Character Integer Long Float Double Boolean Object

From ↓ byte

5.5.1 Reference Type Casting

Given a compile-time reference type S (source) and a compile-time reference type T (target), a casting conversion exists from S to T if no compile-time errors occur due to the following rules.

If S is a class type: • If T is a class type, then either | S | <: | T |, or | T | <: | S |. Otherwise, a compile-time

error occurs. Furthermore, if there exists a supertype X of T , and a supertype Y of S , such

that both X and Y are provably distinct parameterized types (§4.5), and that the erasures of X and Y are the same, a compile-time error occurs.

5.5.1 Reference Type Casting CONVERSIONS AND PROMOTIONS

• If T is an interface type: ◆ If S is not a final class (§8.1.1), then, if there exists a supertype X of T , and

a supertype Y of S , such that both X and Y are provably distinct parameterized types, and that the erasures of X and Y are the same, a compile-time error occurs.

Otherwise, the cast is always legal at compile time (because even if S does not implement T , a subclass of S might).

◆ If S is a final class (§8.1.1), then S must implement T , or a compile-time error occurs.

• If T is a type variable, then this algorithm is applied recursively, using the upper bound of T in place of T .

• If T is an array type, then S must be the class Object , or a compile-time error occurs.

If S is an interface type: • If T is an array type, then S must be the type java.io.Serializable or

Cloneable (the only interfaces implemented by arrays), or a compile-time error occurs.

• If T is a type that is not final (§8.1.1), then if there exists a supertype X of T , and a supertype Y of S , such that both X and Y are provably distinct parameterized types, and that the erasures of X and Y are the same, a compile-time error occurs.

Otherwise, the cast is always legal at compile time (because even if T does not implement S , a subclass of T might).

• If T is a type that is final , then: ◆ If S is not a parameterized type or a raw type, then T must implement S , or a

compile-time error occurs. ◆ Otherwise, S is either a parameterized type that is an invocation of some

generic type declaration G , or a raw type corresponding to a generic type declaration G . Then there must exist a supertype X of T , such that X is an

invocation of G , or a compile-time error occurs.

Furthermore, if S and X are provably distinct parameterized types then a compile-time error occurs.

If S is a type variable, then this algorithm is applied recursively, using the upper bound of S in place of S .

CONVERSIONS AND PROMOTIONS Reference Type Casting 5.5.1

If S is an intersection type A 1 & ... & A n , then it is a compile-time error if there exists an A i (1 ≤ i ≤ n) such that S cannot be cast to A i by this algorithm. That is, the success of the cast is determined by the most restrictive component of the intersection type.

If S is an array type SC [] , that is, an array of components of type SC : • If T is a class type, then if T is not Object , then a compile-time error occurs

(because Object is the only class type to which arrays can be assigned). • If T is an interface type, then a compile-time error occurs unless T is the type

java.io.Serializable or the type Cloneable (the only interfaces implemented by arrays).

• If T is a type variable, then: ◆ If the upper bound of T is Object or java.io.Serializable or Cloneable ,

or a type variable that S could undergo casting conversion to, then the cast is legal (though unchecked).

◆ If the upper bound of T is an array type TC [] , then a compile-time error occurs unless the type SC [] can undergo casting conversion to TC [] .

◆ Otherwise, a compile-time error occurs. • If T is an array type TC [] , that is, an array of components of type TC , then a

compile-time error occurs unless one of the following is true: ◆ TC and SC are the same primitive type.

◆ TC and SC are reference types and type SC can undergo casting conversion to TC .

Example 5.5.1-1. Casting Conversion for Reference Types

class Point { int x, y; } interface Colorable { void setColor(int color); } 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

5.5.1 Reference Type Casting CONVERSIONS AND PROMOTIONS

// 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 .

Example 5.5.1-2. Casting Conversion for Array Types

class Point { int x, y; Point(int x, int y) { this.x = x; this.y = y; } public String toString() { return "("+x+","+y+")"; }

} interface Colorable { void setColor(int color); } 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(" }");

CONVERSIONS AND PROMOTIONS Checked Casts and Unchecked Casts 5.5.2

This program compiles without errors and produces the output: cpa: { (2,2)@12, (4,5)@24, null, null }

5.5.2 Checked Casts and Unchecked Casts

A cast from a type S to a type T is statically known to be correct if and only if S <: T (§4.10).

A cast from a type S to a parameterized type (§4.5) T is unchecked unless at least one of the following conditions holds:

• S <: T • All of the type arguments (§4.5.1) of T are unbounded wildcards • T <: S and S has no subtype X other than T where the type arguments of X are not

contained in the type arguments of T .

A cast from a type S to a type variable T is unchecked unless S <: T . An unchecked cast from S to T is completely unchecked if the cast from | S | to | T | is

statically known to be correct. Otherwise, it is partially unchecked. An unchecked cast causes a compile-time unchecked warning, unless suppressed

by the SuppressWarnings annotation (§9.6.3.5).

A cast is checked if it is not statically known to be correct and it is not unchecked. If a cast to a reference type is not a compile-time error, there are several cases: • The cast is statically known to be correct.

No run-time action is performed for such a cast. • The cast is a completely unchecked cast. No run-time action is performed for such a cast. • The cast is a partially unchecked cast. Such a cast requires a run-time validity check. The check is performed as if the

cast had been a checked cast between | S | and | T |, as described below. • The cast is a checked cast. Such a cast requires a run-time validity check. If the value at run-time is 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 erasure (§4.6) of the type named in

5.5.3 Checked Casts at Run-time CONVERSIONS AND PROMOTIONS

the cast operator. A cast conversion must check, at run-time, that the class R is assignment compatible with the type T , via the algorithm in §5.5.3.

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 may refer to an array whose element type is an interface type.

5.5.3 Checked Casts at Run-time

Here is the algorithm to check whether the run-time type R of an object is assignment compatible with the type T which is the erasure (§4.6) of the type named in the cast operator. If a run-time exception is thrown, it is a ClassCastException .

If R is an ordinary class (not an array class): • If T is a class type, then R must be either the same class (§4.3.4) as T or a subclass

of T , or a run-time exception is thrown. • If T is an interface type, then R must implement (§8.1.5) interface T , or a run-

time exception is thrown. • If T is an array type, then a run-time exception is thrown. If R is an interface: • If T is a class type, then T must be Object (§4.3.2), or a run-time exception is

thrown. • If T is an interface type, then R must be either the same interface as T or a

subinterface of T , or a run-time exception is thrown. • If T is an array type, then a run-time exception is thrown. If R is a class representing an array type RC [] , that is, an array of components of

type RC : • If T is a class type, then T must be Object (§4.3.2), or a run-time exception is

thrown. • If T is an interface type, then a run-time exception is thrown unless T is the type

java.io.Serializable or the type Cloneable (the only interfaces 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 .

CONVERSIONS AND PROMOTIONS Numeric Promotions 5.6

• If T is an array type TC [] , that is, an array of components of type TC , then a run- time exception is thrown unless one of the following is true:

◆ TC and RC are the same primitive type. ◆ TC and RC are reference types and type RC can be cast to TC by a recursive

application of these run-time rules for casting.

Example 5.5.3-1. Incompatible Types at Run-time

class Point { int x, y; } interface Colorable { void setColor(int color); } 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);

This program uses casts to compile, but it throws exceptions at run-time, because the types are incompatible.