001package types.casting; 002 003interface Animal { default public String f () { return "Animal"; } } 004interface Fish extends Animal { default public String f () { return "Fish"; } } 005interface Bird extends Animal { default public String f () { return "Bird"; } } 006class Cod implements Fish { public String f () { return "Cod"; } } 007class Owl implements Bird { public String f () { return "Owl"; } } 008 009public class Main { 010 private Main() {} 011 public static void main(String[] args) { 012 Cod cod = new Cod (); 013 Owl owl = new Owl (); 014 015 /* Implicit upcasts always compile and run ok */ 016 Animal aCod = cod; 017 Animal aOwl = owl; 018 019 /* Explicit upcast causes an unnecessary cast warning */ 020 //Animal aCod2 = (Animal) cod; 021 022 /* Explicit downcasts always compile, but may cause runtime errors */ 023 //Fish f1 = aCod; // implicit downcast: compiler error 024 //Fish f2 = (Fish) aOwl; // explicit downcast: runtime error 025 Fish f3 = (Fish) aCod; // explicit downcast: runtime success 026 027 /* Crosscasting to a class is disallowed by the compiler */ 028 //Cod f4 = (Cod) owl; // crosscast: compiler error 029 030 /* Crosscast can be replaced by upcast+downcast */ 031 //Cod f5 = (Cod) (Animal) owl; // upcast+downcast: runtime error 032 033 /* Crosscasting to an interface is allowed by the compiler */ 034 //Fish f6 = (Fish) owl; // crosscast: runtime error 035 036 /* Casting changes the declared type, but not the actual type */ 037 System.out.println("Animal: " + aCod.f()); 038 System.out.println("Fish: " + f3.f()); 039 System.out.println("Cod: " + cod.f()); 040 } 041}