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}