class TestConversions {

    public static void main(String[] args) {
    
    /** Widening **********************************************/
    
    double d = 2.12345D;
    float f = 150.50F;
    long  l = 15000L;
    int   i = 55;
    char  c = 20;
    short s = 1000;          
    byte  b = 126;           
       
    // following compile ok 
    System.out.println();
    System.out.println("Implicit Widening conversions:");
    System.out.println("------------------------------");
    System.out.println("  byte to short: \t -> " + (s=b) );
    System.out.println("   short to int: \t -> " + (i=s) );
    System.out.println("    int to long: \t -> " + (l=i) );
    System.out.println("  long to float: \t -> " + (f=l) );
    System.out.println("float to double: \t -> " + (d=f) );
    
    // following produce compile error: possible loss of precision
//    System.out.println("byte to char: \t -> " + (c=b) );
//    System.out.println("short to char: \t -> " + (c=s) );    
  
    // following compile ok with cast  
    System.out.println();
    System.out.println("Explicit Widening conversions:");
    System.out.println("------------------------------");    
    System.out.println("cast byte to char: \t -> " + (char)b );
    System.out.println("cast short to char: \t -> " + (char)s );
    

    /** Narrowing **********************************************/
    
    // following produce compile errors
    d = 150.234256421235489645;
    
    System.out.println();
    System.out.println("Implicit Narrowing conversions:");
    System.out.println("------------------------------");
//    System.out.println("double to float:  -> " + (f = d) );
//    System.out.println("  float to long:  -> " + (l = f) );
//    System.out.println("    long to int:  -> " + (i = l) );
//    System.out.println("   int to short:  -> " + (s = i) );
//    System.out.println("  short to byte:  -> " + (b = s) );    
    System.out.println("All require explicit cast");    

    // following compile ok with cast
            
    System.out.println();
    System.out.println("Explicit Narrowing conversions:");
    System.out.println("------------------------------");
    System.out.println("double to float:  -> " + (f = (float)d) );
    System.out.println("  float to long:  -> " + (l = (long)f) );
    System.out.println("    long to int:  -> " + (i = (int)l) );
    System.out.println("   int to short:  -> " + (s = (short)i) );
    System.out.println("  short to byte:  -> " + (b = (byte)s) );    
        
        
    /** Widening Reference ***************************************/
    
    SuperClass sc = new SuperClass();
    SubClass   sb = new SubClass();
    SubClassWithInterface sbi = new SubClassWithInterface();
    SuperInterface si;
    SubInterface subi;
    AlternateInterface ai;
    Object o;
    Cloneable cl;
    
    int[] arr = { 1,2,3 };
    SuperClass[] scArray = { new SuperClass(), new SuperClass() };
    SubClass[] subArray = { new SubClass(), new SubClass() };
    
    // following compile ok
    // note: cannot instantiate an interface
    System.out.println();
    System.out.println("Widening Reference conversions:");
    System.out.println("-------------------------------");
    System.out.println("          class to Object: \t -> " + (o=sc) );
    System.out.println("          array to Object: \t -> " + (o=arr) );
    System.out.println("       class to interface: \t -> " + (subi=sbi) );
    System.out.println("subinterface to interface: \t -> " + (si=subi) );
    System.out.println("       array to Cloneable: \t -> " + (cl=arr) );   
    System.out.println("   ref array to ref array: \t -> " + (scArray = subArray));
            
    // following do compile ok but throw runtime errors
    
    o = new Object();    
    sc = (SuperClass) o;
    si = (SuperInterface) o;
    arr = (int[]) o;
    sb = (SubClass) sc;
    si = (SuperInterface) sc;    
    ai = (AlternateInterface)sc;    // compiles ok, runtime error
    si = (SuperInterface)sc;        // compiles ok, runtime error
     
    }

}

class SuperClass {
    public String toString(){
        return "SuperClass";
    }
}

class SubClass extends SuperClass {
    public String toString(){
        return "SubClass";
    }
}

class SubClassWithInterface extends SuperClass
                            implements SubInterface {
                            
    public void method(){}                            
    public String toString(){
        return "SubClassWithInterface";
    }                            
}

final class FinalClass implements SuperInterface {
    public void method() {}
}

interface SuperInterface {
    public void method();
}

interface SubInterface extends SuperInterface {
    public void method();
}

interface AlternateInterface {
}
