SE450: Types: Casting [35/47] |
What is a downcast, upcast, crosscast?
How are casts checked by the compiler?
How are casts checked by the runtime system?
file:types/casting/Main.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package types.casting; interface Animal { default public String f () { return "Animal"; } } interface Fish extends Animal { default public String f () { return "Fish"; } } interface Bird extends Animal { default public String f () { return "Bird"; } } class Cod implements Fish { public String f () { return "Cod"; } } class Owl implements Bird { public String f () { return "Owl"; } } public class Main { private Main() {} public static void main(String[] args) { Cod cod = new Cod (); Owl owl = new Owl (); /* Implicit upcasts always compile and run ok */ Animal aCod = cod; Animal aOwl = owl; /* Explicit upcast causes an unnecessary cast warning */ //Animal aCod2 = (Animal) cod; /* Explicit downcasts always compile, but may cause runtime errors */ //Fish f1 = aCod; // implicit downcast: compiler error //Fish f2 = (Fish) aOwl; // explicit downcast: runtime error Fish f3 = (Fish) aCod; // explicit downcast: runtime success /* Crosscasting to a class is disallowed by the compiler */ //Cod f4 = (Cod) owl; // crosscast: compiler error /* Crosscast can be replaced by upcast+downcast */ //Cod f5 = (Cod) (Animal) owl; // upcast+downcast: runtime error /* Crosscasting to an interface is allowed by the compiler */ //Fish f6 = (Fish) owl; // crosscast: runtime error /* Casting changes the declared type, but not the actual type */ System.out.println("Animal: " + aCod.f()); System.out.println("Fish: " + f3.f()); System.out.println("Cod: " + cod.f()); } }
The rules are as follows class A {} class B extends A {} class C extends A {} Upcast goes from subtype to supertype: (A)(new B()) Downcast goes from supertype to subtype: (B)(new A()) Any other cast is a "cross cast" At compile time: Cast to interface type is always allowed. Cast to class type is allowed if the it is an upcast or a downcast. The declared type of the cast expression is changed: new B() has declared type B (A)(new B()) has declared type A At runtime: Casts are checked to ensure validity (ClassCastException if not) The actual type of the object is unchanged: new B() has actual type B (A)(new B()) has actual type B