/**
 * Sandeep Desai s_desai@hotmail.com http://www.thedesai.net
 *
 * Objects.java
 * Show all the OOP features like objects, inheritance, polymorphism,
 * exceptions and RTTI (Run-Time Type Identification)
 * You can print this program and read it from top to bottom
 *
 * Book Reference: Thinking in Java 3rd Ed
 *
 * To run this program download the J2SDK 1.4.2 or later from java.sun.sun.com
 *
 * OOPS
 *   encapsulation
 *   polymorphism
 *      overloading (same method name with different
 *          parameters determined at compile time)
 *      overriding (override by inheriting)
 *          when inheriting cannot make access weaker
 *          (public to private not OK, private to public OK)
 *
 *
 * constructor can throw any exception.
 * construct can list exceptions using throws keywords like other methods
 * constructor cannot have native final synchrnoized static
 * constructors are not inherited
 * constructor body can have return statement
 * constructors can call other constructors
 * methods cannot call constructors
 * you can either call super or this in a constructor, but not both
 * c
 *
 * Initializer blocks are executed in the order of declaration.
 * Instance initializer(s) gets executed ONLY IF the objects are constructed.
 * multiple static initializers OK
 * abstract class may not have abstract methods
 * a class with abstract methods has to be declared abstract
 * static void foo() and void foo() in a class cause compile error
 * No way to call grandparents method can only access parent using super
 * You can never cast objects of sibling classes( sharing the same parent ),
 *    even with an explicit cast.
 * variables can have same name as method names
 * Object o = new Integer(10);
 * Object o2 = (String) o; // Class Cast exception at runtime
 *
 *
 * Class declarations can come in any order ( derived first, base next etc. ).
 * top level class cannot be private or protected
 * instance variable cannot be syncrhonized strictfp native abstract
 * private methods become invisible so inherting class,
 *    can redefine them with same name
 * method delcaration access modifiers any order,
 *   but return type has to preced method name
 * concrete class can override method and make it abstract
 * transient and static skipped by serializable
 * variable access decided at compile time (overriden methods at runtime)
 *
 * interface ai {int i=0;}
 * class Parent { int i=ai.i+1; }
 * class Child extends Parent {int i=ai.i+2; }
 * test() { Parent p = new Parent(); Child c = (Child) c; // runtime ClassCast error }
 *
 * // base b = new parent() // throws null pointernull pointer exception
 * class base { String s="b"; base() { print(); } void print() { s.trim(); //NPE } }
 * class parent extends base { String s="p"; void print() { s.trim(); } }
 *
 * class Test extends  {
 * static { int i = 0; System.out.println("a"); }
 * static { int j = 0; System.out.println("b"); }
 * { int j= 0; System.out.println("c"); }
 * { int k = 0; System.out.println("d"); }}
 *
 * Inner classes
 *   generates MyOuter$MyInner.class
 *   declared inside a class
 *
 * Non static inner classes
 *   cannot have a static member.
 *   can have only compile time constants static or final
 *   cannot have an interface
 *   can be abstract, private, public, protected
 *   can refer to outer class member variables
 *   outer class instance implicitly passed to inner class
 *   refer to outer class instance as MyOuter.this
 *   outside of outer class create new
 *      MyOuter mo = new MyOuer();
 *      MyOuter.MyInner mi = mo.new MyOuter.MyInner();
 *
 * Static inner class
 *   is really a top level non nested class
 *   can refer only to static outer class member
 *   outside of outer class create using
 *      MyOuter.MyInnner mi = new MyOuter.MyInner();
 *
 * Method local inner class
 *   declared in a method
 *   can be abstract or final only
 *   can only refer to local variables that are final
 *
 * Anonymous inner class
 *    have no name
 *    can only extend one class or interface
 *    cannot have constructor
 *    local variables marked final
 *
 * Argument local inner class
 *    declared inside a method call
 *
 * Exceptions:
 *   try should end with catch or finally
 *   catch should preced finally
 *   finally always called except if System.out.exit() called
 *   finally called even if catch statement throws exception
 *   finally called even if there is a return statement
 *   inherting methods can remove exception,
 *      but cannot add new exceptions or general exceptions
 *   If exception thrown look for try catch
 *   You can add RuntimeException or Error but not
 *      Exception to inherting method with no exceptions
 *
 *
 */

/**
 * Selected list of RuntimeExceptions
 * ArithmeticException, ClassCastException, ConcurrentModificationException,
 * IllegalArgumentException, IllegalMonitorStateException, IndexOutOfBoundsException,
 * NegativeArraySizeException, NoSuchElementException, NullPointerException,
 * SecurityException, SystemException, UnmodifiableSetException, UnsupportedOperationException
 */


// import java.lang.*; Is automatically imported
// import specific classes, allows us to use this class in this file
import java.util.Vector;
import java.util.Random;

/**
 * All objects inherit from java.lang.Object
 *    good to check instanceof in equals
 *    class Foo { boolean equals(Object o) } compile
 *    error as equals has default package access
 * public void equals(Object o)
 * protected void finalize() // called only once (maybe) exceptions thrown ignored
 * public int hashCode() // good idea to override hashCode and equals together
 * public void notify() // Wake up thread that is waiting for this Objects lock
 * public void notifyAll()
 * public void wait()
 * public void wait(long timeout)
 * public String toString() // Object.toString() returns classname@4ae3
 */


/**
 * +-Object
 * |
 * +--+ Throwable (printStackTrace() method, unwinds stack)
 *    |
 *    +--+ Error (Out of Memory etc) typicall not handled in code
 *    |  +-- AssertionError (empty, primitive datatype and Object constructor)
 *    |
 *    |
 *    +--+ Exception
 *       +--+ IllegalAccessException not runtime
 *       |
 *       +--+ RuntimeException (unchecked exception does not have to be caught)
 *          +-- IllegalArgumentException
 *          +-- ArithmeticArgumentException
 *          +-- NullPointerArgumentException
 *          +-- IndexOutOfBoundsException
 *          +-- UnsupportedOperationException
 *
 */


// Class name and file name has to match, top level class cannot be private
public class Objects { // all classes inherit from java.lang.Object //

 public static void foo() {}
 public static void method(String foo) throws Exception {}
 

  // exceptions are used for error handling
  // exceptions propogate if not caught
  // exception matching done on catch clause
  public static void exceptions()  {
    int[] ai = new int[2];
    try {
      ai[3] = 4;  // gaurded region
    } catch (IndexOutOfBoundsException ie) { System.out.println(ie); }
  }

  public static void objects() {
    // uses classes and interfaces defined below
    // since inner classes require a reference to outer class object
    // we have to do a outerClassInstance.new
    Rectangle arectangle = new Rectangle();
    // 1) allocates memory for Rectangle object
    // 2) Call base class constructor (Shape )
    // 3) Call base class constructor (Object )
    // 4) Call derived class constructor in order of inheritance
    // 5) member initializers
    // 6) Call Rectangle constructor() of class for which
    //               object is being created (Rectangle)
 
    Rectangle arectangle2 = new Rectangle(2, 2);
    // In this case Rectangle constructor called first
 
    Circle acircle = new Circle(3);
    Shape[] ashape;
    ashape = new Shape[2];
    ashape[0] = arectangle; // upcast is safe
    ashape[1] = acircle; // upcast is safe
    // Polymorphism, java at runtime figures out the right draw method to call
    ashape[0].draw(); // will call Rectangle.draw()
    // downcast can be fail at runtime with ClassCastException
    Rectangle rect = (Rectangle) ashape[0];
 
    // since ashape[1] refers to a Circle this line will fail at runtime
    try { rect = (Rectangle) ashape[1]; }
    catch (ClassCastException e) { System.out.println("class cast exception"); }

    // use RTTI (Runtime Type Identification)
    // instanceof checks if object is of specific class
    // or inherits from sepcific class
    if (ashape[0] instanceof Rectangle) {} // true
    if (ashape[0] instanceof Shape) { } // true
    if (!(null instanceof Rectangle))
    { System.out.println("null instanceof false"); }
    if (ashape instanceof Object) {} // true
    Print p = acircle;
    if (p instanceof Object)
    { System.out.println("Circle instanceof Print Interface"); }

    // Construct instance of a class equivalent to a new
    // Java forces use to check for the exceptions
    try { Rectangle rect2 = (Rectangle) Rectangle.class.newInstance(); }
    catch (IllegalAccessException ie) {}  //
    catch (InstantiationException ie2) {} // Constructor threw some exception
    Rectangle rect3 = new Rectangle();
 
    System.out.println("Order of constructor calls");
    // ***** constructors for all parent classes always called
    Circle c = new Circle(1, 1.0f);
 
    // show how object are passed by reference, so you can change object
    // contents but not reference
    // show how to reference static data and methods
  }
 
  // all exceptions thrown by a method have to be listed
  // two types of exceptions checked and unchecked (Runtime)
  // catching unchecked exceptions is optional e.g are divide by zero,
  // Array Illegal out of bound exception
  // method inherited new Checked Exceptions cannot be added
  // or more general checked exceptions cannot be listed
  // Any method optional to list any Error or RuntimeExceptions
 
  // Note NegativeValueException and InvalidValueException class defined below
  // all three ways listed below are valid ways to for this method declaration
  public static void incrementValue(int ai)
       throws NegativeValueException, InvalidValueException
  //public static void incrementValue(int ai)
  //throws InvalidValueException // just listed parent exceptions class
 
  //public static void incrementValue(int ai) throws Exception
  {
    if (ai < 0) throw new NegativeValueException("value is negative", 10);
    if (ai > 10) throw new InvalidValueException("value is too large", 10);
    // (unchecked) runtime exception does not have to be caught
    if (ai % 2 == 0) throw new SomeRuntimeException();
    ++ai;
  }
 
 
  public static void exceptions2() {
    int a = 0;
    // catch is optional, must have catch or finally
    // list all subclass (specific) exceptions first and then general
    // will generate compilation error
    // try {} catch(Exception e) {} catch(InvalidValueException e) {}
    try {
      incrementValue(a);
      incrementValue(-1);   // will throw exception
      incrementValue(2); // this line never run
      return; // finally is executed even if return in try code
    } catch (NegativeValueException ne) {
        ne.printStackTrace(); // where exception was thrown
        System.out.println(ne.getLocalizedMessage());
      }
      catch (InvalidValueException ne) { }
      catch (Exception e) {} // Will catch all exceptions
      catch (Throwable t) {} // Will catch all runtime exceptions
      // Note that exceptions thrown in finally are lost
      finally {
        // need try catch here to if calling methods that throw
        // checked exceptions
      } // optional finally is called, put cleanup code here e.g closing files
  }
 
  // Java 1.4 adds a new feature for chaining exceptions
  public static void wrapException() throws WrapException {
    int a = 0;
    try {
      incrementValue(-1);   // will throw exception
    } catch (Exception e) {
      // capture information about original cause of exception
      throw new WrapException("don't like value", e);
      // lose all information about original cause of exception
      //throw new WrapException("don't like value");
    }
  }
 
  public static void exceptions3()  {
    try {
      wrapException();
    } catch (WrapException we)  {
      System.out.println("Caught wrap exception");
      Throwable t = we.getCause(); // this is the actual exception thrown
      // prints correct stack trace of actual code throwing exception
      we.printStackTrace();
    }
  }
 
  /**
   * Overloaded methods (Which method to call determined at compile time)
   * Overloaded Rules:
   *   overloaded methods must change the argument list
   *   overloaded methods can change the return type
   *   overloaded methods can change the access modifier
   *   overloaded methods can declare new or broader checked exceptions
   *   A method can be overloaded in the same class or in a subclass
   */
  static void m1(int x) {}
  //static int m1(int x) {} // will not compile
  static void m1(float x) {}
  // will call m1(Shape) method not m1(Rectangle)
  // Shape s = new Rectangle(); overloadedMethod(s);
  static void m1(Shape x) {}
  static void m1(Rectangle x) {}
 
  // If your code has a lot of instanceof then your are not doing proper OOP Code
  public static void rtti() {
    // Load a class
    try { Class.forName("Tutorial"); }
    catch (ClassNotFoundException e) {}
    Class booleanClass = boolean.class; // each primitiv data type has a .class
    //Boolean.TYPE
    Package packageName = Objects.class.getPackage();
    String foo = null;
    try { foo = (String) String.class.newInstance();  }
    catch (IllegalAccessException e) {}
    catch (InstantiationException e) {}
    Class stringClass = foo.getClass();
    boolean b = String.class.isInstance(foo);

  }
 
  public static void anonymousInnerClass()  {
    // local variables accessed from inner class have to be final
    // because the class may pass this variable to some other class
    //
    final Button b = new Button();
    String s;
    b.name = "foo";
    Controller c = new Controller();
    // Anonymous inner class, we are implementing class within an
    // argument to a method
    // can only extend 1 class or 1 interface
    // translates to b.addActionListener(new class Objects$1
    //     implements ActionListener() {
    b.addActionListener(new ActionListener() {
      // can't define constructor, so have to put the code
      // as shown below
      { System.out.println("no constructor"); }
      // local variables accessed from inner class have to be final
      public void actionEvent() { System.out.println(b.name); }
      // can call outerclass methods since we have reference
      // to outer class object
      public void anotherEvent() { foo(); }
      }
    ); // **** ; is very important only place class declaration ends in ;
    c.callback();

    // can have class within a method goes out of scope after the method
    class Foo { public void foo() {} }
    {
      // class with any {} scope could be an if, while etc
      class Foo { public void foo() {} }
    }
  }
 
  static int si = 2; // allocated only once per program run
  private static float staticMethod() { return 4.2f; } // can’t reference this.i

  // this code is excuted when Java loads the Tutorial class
  static { si = 3; System.out.println("Tutorial class loaded");  }

  public static void main(String[] args) {
    exceptions();
    objects();
    exceptions2();
    exceptions3(); // Chained Exceptions
 
    // only one instance of static for the whole process
    si = 3;
    Objects.si = 4; //
    Objects.staticMethod();
 
    Objects t = new Objects(); // create a new instanace of tutorial
    // no need to free this memory it will be garbage collected when
    // there are no live threads referenceing this object
 
    int x; // Not initialized, can have any value
    {
       // int x = 3; // Not allowed
       int y = 3;
    } // y out of scope here
 
    Vector v = new Vector(); // requires import java.util.Vector;
    // does not require import as we are using full package name
    v = new java.util.Vector();
    v.add(new String("a")); // automatic upcasting from String to object
  }
 
  // aa’s reference cannot be changed but you can still to things like aa.trim()
  // to change contents of object
  final String aa = new String("a ");
  final static int fj = new Random().nextInt();
  //final int qfinal;
 
  //someMethod(new Integer[] { new Integer(1), new Integer(2) });
}

/**
 *
 * Cannot run java MyOuter$MyInner
 * Innner class cannot be protected or final
 * Inner class can access outer class private variables
 * For Method Inner class, can only access local variables that are final
 *
 * Inner classes
 * 1) A class defined within a method
 * 2) A class defined within a scope inside a method
 * 3) An anonymous class implementing an interface or a class
 * 4) An anonymous class extending a class that has a nondefault constructor
 * 5) An anonymous class that performs field initialization
 * 6) An anonymous class that performs construction using instance initialization
 *   (anonymous inner classes cannot have constructors)
 *
 */

class MyOuter {
  class MyInner {
    public void foo() {
      int a = MyOuter.this.j; // To refer
      int b = j; // To refer
    }
    //Inner class cannot have static member
    //static int j;
    // final static OK
    final static int j = 0;
    // interface foo {} // will not compile interface implicitly static
  }
  int j;
  interface MyInnerInterface {}
}

class InheritInner extends MyOuter.MyInner {
  //! InheritInner() {} // Won't compile
  InheritInner(MyOuter wi) {
    wi.super();
  }
  public void foo2() {
    // Inner class in a method can only be instantiated in the class
    // as scope of class within method
    // Method local cannot be public, private or protected, static or transient
    // only abstract and final
    class methodInnerClass { }
    methodInnerClass mi = new methodInnerClass();
  }
  public static void innerClass() {
    MyOuter mo = new MyOuter();
    MyOuter.MyInner mi = mo.new MyInner();
  }
}

//static class Foo {} // Illegal

class MyOuter2 {
  // nested static class are also called Top Level nested class
  static class MyInner2 { }
 
  public static void innerClass2() {
    MyOuter2 mo2 = new MyOuter2();
    // creating objects with static inner class
    MyOuter2.MyInner2 mi2 = new MyOuter2.MyInner2();
  }
}


// Exceptions are classes you can have any methods or members
class InvalidValueException extends Exception
{
  InvalidValueException(String msg, int max) { super(msg); this.max = max; }
  public int max = 0;
}

//
class NegativeValueException extends InvalidValueException
{
  NegativeValueException(String msg, int max) { super(msg, max); }
}

// RuntimeExceptions are typically programmer errors and
// ideally should not happen
class SomeRuntimeException extends RuntimeException {}

// Java 1.4 feature
// /we can chain exceptions so that the user can trace the original exception
class WrapException extends Exception {
  // if this constructor is used the cause and the stack trace of
  // the original exception is lost
  WrapException(String msg) { super(msg); }
  // this constructor ensures that we capture the orignal cause
  // and stack trace of this exception
  WrapException(String msg, Exception e) { super(msg, e); }
}

// interface can have data and method declarations but no code
// an instance of an interface cannot be created
// they are useful for declaring constants
// Everything is public by default
// interface implicitly abstract
interface Print { // Note interface does not extend Object
  int i = 3; // static and final and has to have a value (basically a constant)
  public static final String s = "foo";
  int len = s.length();
  void print(); // methods public abstract by default
  //public abstract void print();
  // private int i; cannot have private in an interface
}

// interface can extend another interface
interface Print2 extends Print {}

// public is required for print otherwise compile error
class Print3 implements Print { public void print() {} }

// A class contains data and methods (functions)
// An instance of an abstract class cannot be created
// May contain zero or more abstract methods
// keywords strictfp, native, syncrhonized, static are implementation
//    specific so illegal with abstract
// strictfp class or method modifier
// native method only modifier
abstract class abstractClass implements Print {}

abstract class Shape {

  // Constructor has the same name as the class. It is called when an instance
  //     of this class is created
  // It is used to initialize the instance (object)
  // Call only final or private methods in a constructor as inheritance
  //   can cause problems
  // If no constructors declare this is created by default
  public Shape() { base = 0; System.out.println("Shape() constructor called");}
  public Shape(int base) { this.base = base; } // Another constructor
  // this is a reference to self
 
  // forces that class be declared abstract and that all classes inherting
  // from this class implement this method
  public abstract void draw();

  // class inherting cannot downgrade from public to private
  public double area() { return base; }
 
  protected void protectedMethod() {}
  public void fooMethod() throws InvalidValueException {}

  public int base = -1;
 
  /**
   * Maybe called when memory is garbage collected,
   * recommended not to use, can be used for debugging
   * Will be called only once
   * exceptions thrown ignored but garbage collection halted
   * System.gc() request to force garbage collection
   */
  protected void finalize() throws Throwable {}
}

// Rectangle inherits from Shape, can inherit from only one class

class Rectangle extends Shape {
 
  private int length;

  // constructors can add to base class exceptions
  public Rectangle() {} // will call the Shape constructor first
  public Rectangle(int width, int length) { super(width); this.length = length; }

  // method can be only called within the class, is automatically final
  // as it cannot be overriden
  // child class can have foo1() method which will be different
  private void foo1() {}
  // can be called by methods in this class and by classes inherting from
  // this class and this package
  // becomes private in child class
  protected void foo2() {}
  // default is package access can be called by any class in this package
  void foo3() {}
  public void foo4() {} // can be called by anybody
  final public void foo5() {} // method cannot be overridend by child class

  /**
   * Overriding methods
   * Overriding Rules:
   *   argument list must match exactly
   *   return type must match exactly
   *   access level must not be more restrictive
   *   access level can be less restrictive
   *   cannot throw new or broader exceptions
   *   can throw narrow or fewer exceptions
   *   cannot override method marked final
   *   if method can't be inherited you cannot override it
   *   overloaded methods can change return type overriding methods cannot
   */
  public double area()  {
    super.area(); // Call parent class area method
    return base*length;
  }
 
  // we made parent class method from protected to public here
  public void protectedMethod() {}

  public double areaWithCheck() throws NegativeValueException {
    super.area(); // Call parent class area method
    if (base < 0 || length < 0)
       throw new NegativeValueException("base or length is negative", 10);
    return base*length;
  }
 
  // inherited method can throw inherited exceptions
  // cannot add new exceptions ?????
  // @see
  public void fooMethod() throws NegativeValueException {}
 
  public void draw() { System.out.println("draw Rectangle length=" + length); }
  // can have same method with different arguments, overload method names
  public void draw(int f) { }
  // can't have two method names with same arguments but different return types
  // public int draw(int f) { }
 
  // static int ici = 2; // Inner class cannot have static
 
  String type;
  { // useful for anonymous classes
    type = "Rectangle";
    System.out.println("called on new Rectangle before constructor");
    area();
  }

  private class test {} // inner class can be private
}

/**
 * A class can implement more than one interface but can extend only one class
 *  Constructor Rules:
 *    Same name as class
 *    no return type
 *    not inherited
 *    super(..) always called
 *    Can be private (Singleton Design Pattern)
 *    OK to have method with same name as constructor (Bad practice)
 *    If no constructor provided default no arg constructor created
 *      (has same access modifier as class)
 *      includes super() call to parent class
 *    If constructor provided then default constructor not created
 *    First statement must be call to this() or super()
 *    Illegal to access instance variables before super() call finishes
 *    Illegal -> {int z; foo() { super(z); }}
 *    Can pass static in above example
 *    Abstract classes have constructors
 *    interfaces do not have constructors
 *    methods cannot call constructors, only constructors can call constructors
 *       use this() to call constructor from another constructor
 *       super() or this() should be first line so can't call both
 *
 * Note overloaded constructors below
 */
//
class foo {
  foo(int x) {  }
  // this calls foo(int x)
  foo(float y) { this((int) y); }  } //
//class boo1 extends foo { }  // will not compile
//class boo2 extends foo { boo2(int y) { } }  // will not compile
class boo2 extends foo {
  // can only reference static method or variable in super() call
  boo2(int y) { super(m(y)); }
  static int m(int x) { return x; }
  }
class test {
  public static void testfoo() {
     // will not compile as constructor not inherited
    //boo2 b21 = new boo2(1.0f);
    boo2 b22 = new boo2(1);
  }
}


// nobody can inherit from Circle all methods in this class
// will automatically be final
final class Circle extends Shape implements Print {
  public Circle(int radius) { super(radius); }
  public Circle(int radius, float precision)
  { System.out.println("Circle constructor(int, float) called"); }
  public void draw() { System.out.println(" draw circle "); }
  public void print() { draw(); } // have to implement print()

  // inner class can access outer class methods as inner class object cannot
  // be created without
  // a reference to outerclass object
  class innerClass { void method() { draw(); } }
}

// This example is based on the Java UI event callback model
interface ActionListener {
  public void actionEvent();
  public void anotherEvent();
}

class Button   {
  public String name;
  public void addActionListener(ActionListener al) { this.al = al; }
  public void callback() { if (al != null) al.actionEvent(); }
  ActionListener al;
}

class Controller   {
  public void add(Button b) { button = b; }
  public void callback() { button.callback(); }
  Button button;
}