The following are in the Java Class Library:

public class Throwable extends Object 
public class Exception extends Throwable
public class RuntimeException extends Exception
public class NullPointerException extends RuntimeException

[00] Draw the 5-node class hierarchy for the aforementioned classes.

   Object 
      Throwable
         Exception
            RuntimeException
               NullPointerException

[01] Record the unchecked exceptions, if any.
   RuntimeException  and  NullPointerException

   Note:  All descendent classes of class RuntimeException 
          are unchecked exceptions.

[02] Evaluate:   new NullPointerException() instanceof Exception
   true   NullPointerException is-a grandchild of Exception; therefore, 
          via inheritance, an instance of class NullPointerException 
          is-an instance of class Exception

[03] Record the output for the following program.
class DanglingPointerException extends NullPointerException { }
class CopyPasteException extends Exception { }

public class E {
   public static String x = "foo", y = "goo";
   public static boolean f = false;
   public static void main(String[] argv) {
      try {
         System.out.println(getOriginalX());
         setXtoY();
         System.out.println(getOriginalX());
      } catch(Exception e) {
         if (e instanceof DanglingPointerException)
            System.out.println("dang it!");
      }
      try { 
         paste(copy());
      } catch(CopyPasteException e) {
         System.out.println("copy/paste w/o citing owner is a no-no");
      }
   }

   public static void setXtoY() { x = y; f = true; }
   public static String getOriginalX() throws DanglingPointerException {
      if (f) throw new DanglingPointerException();
      return x;
   }
   public static boolean copy() { return false; }
   public static void paste(boolean cited) throws CopyPasteException {
      if (cited) return;
      throw new CopyPasteException();
   }
}
   
foo
dang it!
copy/paste w/o citing owner is a no-no
Exercises 4-8 use the following from the Java Class Library:
public abstract class Number extends Object implements Serializable
public final class Byte extends Number implements Comparable
public class StringBuffer
public interface Serializable
[04] Briefly explain why   class A extends StringBuffer, Number { }   does not compile.
   Java is a single-inheritance language. In addiion, 
   class A cannot extends the abstract class Number.

[05] Briefly explain why   class B extends Byte { }   does not compile.
   Byte is declared to be a final class and final classes can't be extended.

[06] Briefly explain why   Number n = new Number();   does not compile.
   class Number is declared abstract and 
   abstract classes cannot be instantiated.

[07] Briefly explain why   Serializable s = new Serializable();   does not compile.
   Serializable is an interface and
   interfaces cannot be instantiated.

[08] Evaluate:   new Byte((byte)42) instanceof Serializable
   true  class Byte extends Number and class Number implements 
         Serializable; therefore, via inheritance, a Byte object 
         is an instanceof Serializable.

[09] Briefly explain why   long y = 42; int x = y;   does not compile.
   Cannot assign a larger data type to a smaller data type 
   unless a typecast is used on the right-side operand of 
   the assignment operator.  Example:  int x = (int)y

Exercise 10 uses the following method...
public static int zzzz(int x, int y, String s) {  
   System.out.println(s + "zzzz(" + x + ", " + y + ")");
   s += "...";
   if (y != 0) return zzzz(y, x % y, s);
   return x;
}
[10] Evaluate:   zzzz(56, 32, "")
   zzzz(56, 32)
   ...zzzz(32, 24)
   ......zzzz(24, 8)
   .........zzzz(8, 0)
   zzzz(56, 32) = 8

   GCDverbose.java  (hyperlinked to on weeks 5, 6, and 7)

Exercise 11 uses the following two methods...

public static int whatever(long n) { 
   return whatever(n, 0); 
}

public static int whatever(long n, int c) {
   if (n == 0) return c;
   ++c;
   return whatever(n / 10, c);
}
[11] Evaluate:   whatever(32767)
   whatever(32767)
      return whatever(32767, 0)
         return whatever(3276, 1)
            return whatever(327, 2)
               return whatever(32, 3)
                  return whatever(3, 4)
                     return whatever(0, 5)
                            5  // because n == 0
   evaluates to 5
[12] Record the output for class Main when it is executed with no command-line arguments (i.e. argv.length == 0 is true).
public class Main {
   static final boolean[] BOOLS = { false, false, true, false, true, };
   static final int MAX_BITS = BOOLS.length, DONE = -1, ON = 1, OFF = 0;
   static int count = 0;
   public static void main(String[] argv) {
      if (count == MAX_BITS) { 
         System.out.println(argv[0]); 
         System.exit(0); 
      }
      if (argv.length == 0) { 
         argv = new String[1]; 
         argv[0] = new String();
      }
      if (next() == ON) One.main(argv);
      else Zero.main(argv);
   }
   public static int next() {
      if (count == MAX_BITS) 
         return DONE;
      int bit = OFF;
      if (BOOLS[count]) 
         bit = ON;
      ++count;
      return bit;
   }
}
class Zero {
   public static void main(String[] argv) {
      argv[0] += "0";
      switch (Main.next()) {
         case Main.DONE: Main.main(argv); 
         case Main.ON  : One.main(argv); 
         case Main.OFF : main(argv);
      }
   }
}
class One {
   public static void main(String[] argv) {
      argv[0] += "1";
      switch (Main.next()) {
         case Main.DONE: Main.main(argv); 
         case Main.ON  : main(argv); 
         case Main.OFF : Zero.main(argv);
      }
   }
}
   00101

   Main.java  (hyperlinked to on weeks 9 and 10)
Exercises 13-15 use the following interface and classes.
interface Fooable { void foo(); }
class V implements Fooable {
   public void foo() { System.out.print("g"); }
}
class W { };
class X implements Fooable { 
   public void foo() { System.out.print("o"); }
}
class Y { }
class Z implements Fooable {
   public void foo() { System.out.print("t"); }
}
class XX extends X { }

public class Poly {
   public static void main(String[] argv) {
      Object[] objects = { new V(), new W(), new X(), new Y(), 
                           new Z(), new XX(), };
      for (int i = 0; i < objects.length; i++)
         if (objects[i] instanceof Fooable)
            ((Fooable)objects[i]).foo();
      System.out.println();
   }
}
[13] Record the output for class Poly.
   goto   (followed by a newline)

[14] Briefly explain how   class Poly   uses polymorphism.
   There are multiple foo() methods and the JVM determines
   which foo() to call at run-time (versus the compiler 
   generating code to call the right method at compile-time).

[15] Note:   new Y()   compiles. Briefly explain why   new Y().foo()   does not compile.
   class Y does not implement a foo() method.  In addition,
   class Y extends Object, so it doesn't inherit a foo() method.

Exercises 16-18 use the following 2-dimensional array.

String[][] s = {
   { "don't", "do", },
   { "add", "multiply-by", "divide-by", },
   { "five", "zero", "3.1416", "negative one", },
};
[16] Evaluate:   s.length
   s.length evaluates to 3 

[17] Evaluate:   s[1].length
   s[1].length evaluates to 3 

[18] Record what the following statement prints:
      System.out.println(s[0][0] + " " + s[1][2] + " " + s[2][1]);
   don't divide-by zero

Exercises 19-21 use class Override.
public class Override {
   private int x = 42;
   private int y = 37;
   private int z = -1;

   public Override() { }
   public Override(int a, int b) { x = a; y = b; }

   // [20] TBI (To Be Implemented)...
   // String format:  value_of_x,value_of_y,value_of_z
   //
   public String toString() { }

   // [21]  TBI (To Be Implemented)...
   // Two Override objects are equal if the have the same 'y' values.
   //
   public boolean equals(Override that) { }

   public static void main(String[] argv) {
      Override[] o = { new Override(), new Override(37, 42), new Override() };
      System.out.println(o[0]);
      for (int i = 1; i < o.length; i++) 
         System.out.println(o[i] + "..." + o[0].equals(o[i]));
   }
}
Note: Without overriding the inherited toString() and equals() methods, class Override output was the following:
   Override@5ccd43c2
   Override@4aa8f0b4...false
   Override@7960847b...false
[19] Briefly explain how the aforementioned output was generated.
   The  toString()  and  equals()  methods inherited from class Object 
   get called. The class Object  toString()  returns a String containing
   the class name and a hash code (possibly an address). The class
   Object  equals()  method evaluates  this == that  (i.e. addresses
   are compared; not object contents).

[20] Implement (override) the toString() method in class Override.
   public String toString() {
      return x + "," + y + "," + z;
   }

[21] Implement (override) the equals() method in class Override.
   public boolean equals(Override that) {
      return this.y == that.y;
   }

Note: The output of class Override should look as follows after [20] and [21] have been completed.

   42,37,-1
   37,42,-1...false
   42,37,-1...true