Home Previous Next

CSC205::Lecture Note::Week 05
Assignments | Code | Handouts | Resources | Email Thurman { compufoo::Twitter | Facebook | YouTube}
GDT::Bits:: Time  |  Weather  |  Populations  |  Special Dates

Overview Assignment(s)[program] #AmusementRide [due 2/25/02018]

Code [OOP] Robot.java | Robot2.java | Foo.java
[exceptions] Exceptions.java | TestExceptions.java | Xception.java
[multi-dimensional arrays] MultiArrays.java | TwoDimensionalArrays.java | BYTES.java | ThreeDimensionalArray.java
[interfaces] InterfaceExample.java | InterfaceEG.java | I_ExitStatus.java | TestI_ExitStatus.java
[interfaces continued] TestSerializable.java | TestClone.java | CSC205_Containers
[recursion] Factorial.java | Countdown.java | Power.java | PrintLD.java | Reverse.java | Fibonacci.java | GCD.java {GCDverbose.java}


Exceptions are "exceptional" conditions that can occur while a program is executing (i.e. running). Some exceptions are caused due to software defects (e.g. using a null object handle, or indexing beyond the bounds of an array).

   String s = null;
   String s1 = "hello";
   if (s.equals(s1)) { ... }     //this will cause an exception
   int[] array = new int[10];
   array[array.length] = 200;    //this will cause an exception

Exceptions are also generated by errors that are beyond the control of the program (e.g. the program needs to access a file that doesn't exist, or the program needs to fetch a webpage given an invalid [mal-formed] URL).

Exceptions can be "caught" by programs, but if an exception does occur that isn't caught, then the program (assuming it is non-graphical) terminates. (A GUI program returns to the user interface).

Exceptions are objects that are created from the Exception and RuntimeException classes.

   Error               Exception
   .....               /  ...  \
                  IOException   RuntimeException 
                    (checked)     (unchecked)

There are two categories of exceptions: checked and unchecked. Checked exceptions must be caught (otherwise, your program will not compile). Unchecked exceptions typically are not caught (i.e. they cause your program to terminate when they occur).

A method can throw an exception when it encounters a situation it cannot handle. There are numerous methods that come with the JCL (java class library) that throw exceptions.

A method declaration must contain a list of the the checked exceptions it may throw.

   public int someMethod() throws IOException, MalformedURLException

A method does not need to declare RuntimeException inherited exceptions that it may throw.

If a method overrides a method from a parent class, then the child method cannot throw more checked exceptions that the parent method does.

A method can say it throws exceptions that it really doesn't throw.

Catching an Exception

Whenever a method is called that throws a checked exception, then that method call must be called from within a try block and an exception handler (catch block) must be implemented.

   try {
   } catch (IOException e) {

If an exception occurs, then the flow control of the program jumps to a catch block. All remaining statements, if any, within the try block are skipped. If no exception is thrown, then the catch blocks are skipped.

A try block must be a compound statement. Ditto for the catchblocks.

The catch blocks are passed an argument: a reference to the exception (which may or may not be used).

Throwing an Exception

An exception is thrown as follows.

   throw new EOFException();


   throw new EOFException("file's empty");
      //supply additional information about the exception
      //this information can help the client "fix" the problem

A method that throws an exception does not return to the caller.

An exception can be re-thrown. You may want to do this in the event an exception occurs: you catch it locally to clean up any locally allocated objects and/or system resources, and then "pass" the exception on to those who know about handling it.

Exception A can be caught, and exception B can be thrown.

Creating an Exception Class

You can create your own exceptions by extending Exception or some child class of Exception.

   class MyException extends Exception {
      public MyException() {}
      public MyException(String msg) { super(msg); }

The following exception terminology was obtained from Just Java by Peter van der Linden:

Note Java Other Languages
An error condition that happens at run time Exception Exception
Causing an exception to occur Throwing Raising
Capturing an exception that has just occurred, and executing statements to resolve it in some way Catching Handling
The block that does this Catch clause Handler
The sequence of call statements that brought control to the method where the exception happened Stack trace Call chain
Miscellaneous Comments

Detect errors at a low level, handle them at a high level.

Use exceptions only for exceptional situations.

YouTube.com::CS 61B Lecture 14: Exceptions

{TopOfPage} {Oracle.com::API Specification | Tutorial} {Derek Banas Videos} {Data Structure Visualizations}

Multi-dimensional Arrays

Multi-dimensional arrays are arrays-of-arrays. Example: a two-dimensional array is an array of one-dimensional arrays.

   int someArray[][];  // someArray  will reference an array whose elements
                       // are of type:   array-of-int

    * create a 4 element array of 4 element int arrays
   someArray = new int[4][];        // create a 4 element array
   for (int i = 0; i < 4; i++)
      someArray[i] = new int[4];

   int[0][0]  int[0][1]   int[0][2]   int[0][3]
   int[1][0]  int[1][1]   int[1][2]   int[1][3]
   int[2][0]  int[2][1]   int[2][2]   int[2][3]
   int[3][0]  int[3][1]   int[3][2]   int[3][3]

    * create a 4 element array of variable length int arrays
   a = new int[4][];
   for (int i = 0; i < 4; i++)
      a[i] = new int[i+1];

   int[1][0]  int[1][1]
   int[2][0]  int[2][1]  int[2][2]
   int[3][0]  int[3][1]  int[3][2]  int[3][3]

   The EXPR  a[i]  accesses the  i'th   one-dimensional array.

   The following code snippet creates a 2x3 table of Foo objects.

      Foo[][] foo = new Foo[2][3];
      for (int i = 0; i < foo.length; i++) 
         for (int j = 0; j < foo[i].length; j++)
            foo[i][j] = new Foo();


      Foo[][] foo = new Foo[2][];
      for (int i = 0; i < foo.length; i++)  {
         foo[i] = new Foo[3];
         for (int j = 0; j < foo[i].length; j++)
            foo[i][j] = new Foo();

Excluding some mathematical and scientific computing, multi-dimensional arrays rarely exceed two dimensions.


{TopOfPage} {Oracle.com::API Specification | Tutorial} {Derek Banas Videos} {Data Structure Visualizations}


From the The Java Programming Language by Arnold, Gosling, Holmes.

The fundamental unit of programming in Java is the class, but the fundamental unit of object-oriented design is the type. Interfaces define types in an abstract form as a collection of methods or other types that form the contract for that type.

An interface is defined using the keyword interface rather than class.

An interface contains no instance variables, nor does it contain any method implementations. You cannot create instances of an interface.

   interface Foo { ... }

   //! Foo f = new Foo();   // not legal

An interface can declare three kinds of members:

All interface members are implicitly public.

A class guarantees to implement the methods of an interface by using the implements keyword when the class is defined.

   class X implements Y

Any class that implements an interface must define (i.e. implement) the methods, if any, declared in the interface.

A class can implement more that one interface. In addition, a class can extend another class and still implement one or more interfaces.

   class X implements Y, Z { ... }
   class X extends A implements Y, Z { ... }

To an extent, interfaces support the concept of multiple inheritance.

Common interfaces from the java.lang package:

An interface can be used to "tie" together classes that are in separate inheritance trees.

                Assignment               Interface:  Submitable
            Exam   Program   Homework
            ...    ...       ...

              Game                       Interface:  Submitable
  Guessing  Yahtzee   Blackjack
  ...       ...       ....

Another example...

An interface can be used to encapsulate a collected of related manifest constants (i.e. simulate an enum in C).

   interface ExitStatus {
      int EXIT_SUCCESS = 0;
      int EXIT_FAILURE = 1;

When an interface declares named constants, then they are implicitly defined to be public, static, and final. [blank finals are not allowed]

Methods declared in an interface are implicitly abstract.

An interface can extend (i.e. inherit) other interfaces.

   interface Sortable { ... }
   interface Searchable { ... }
   interface Container extends Sortable, Searchable { ... }
Any class that implements interface Container must also implement the Sortable and Searchable interfaces.

Although you cannot instantiate an object using an interface, you can use an interface as the type for variable and assign to that variable any object whose class implements the interface. This allows for polymorphic run-time binding.

   interface Container { ... }

   class List implements Container { ... }

   List list = new List();
   Container c = list;  // list is a container

From a naming convention perspective, many interfaces have a -able suffix applied to them.

{TopOfPage} {Oracle.com::API Specification | Tutorial} {Derek Banas Videos} {Data Structure Visualizations}

Object Serialization

Any object that implements the Serializable interface can be turned into a sequence of bytes that can be restored fully into the original object.


The Serializable interface is used as a flag -- it has no methods. Some objects may not want to be serialized.

To serialize an object you create some sort of OutputStream object and wrap it inside an ObjectOutputStream object. Then, the object can be serialized by calling writeObject(). Reversing the process is accomplished by creating an InputStream inside a ObjectInputStream and calling the readObject() method.

When an object is serialized, so are all the references it may contain to other objects.

- Object Serialization (java1.1)
   * useful for saving the state of an application/applet
   * objects serialized/deserialized with  ObjectOutputStream  and
     ObjectInputStream, respectively, using the  writeObject()  and
     readObject()  methods
   * primitive types written to stream as if using DataOutputStream;
     otherwise,  writeObject() is called recursively to serialize
     other objects (arrays, strings, objects) -- infinite recursion
     is not a problem (so they say); can end up with an entire
     graph object serialized
   * not all objects can or should be serialized
   * a class is serialable iff it implements Serializable 
      (or Externalizable); no methods defined -- it is a
      marker interface
   * Component implements Serializable; thus, all AWT components
     can be serialized
   * transient  indicates that a field should not be serialized
   * custom serialization is accomplished by overriding  writeObject()
     and  readObject(), and by using  defaultWriteObject()  and
     defaultReadObject() -- note: they must be declared  private
   * classes are assigned a version # -- cannot deserialize a
     class that has a different version # than what was used when
     it was serialized;  'serialver'  program
        + static final long serialVersionUID = 19971209L;
   * serialized applets
      + <applet code=appletName.ser ...>
      + applets can be shipped in a pre-initialized state
   * Externalizable
      + ObjectOutputStream and ObjectInputStream use the
         writeExternal() and readInternal() methods instead
         of writeObject() and readObject(); allows the class
         to take complete control over writing/reading their state

{TopOfPage} {Oracle.com::API Specification | Tutorial} {Derek Banas Videos} {Data Structure Visualizations}

Object Cloning

Objects cannot be cloned unless they are created using a class that implements the Cloneable interface.

For a class to use the default implementation of Object.clone(), it must implement the Cloneable interface.

The Cloneable interface is an empty interface -- it is used as a tag only. In many cases, classes that can be cloned override Object.clone().

Object.clone() does a bit-wise copy, which works fine for primitive types, but not necessarily with references. Only individual classes know how to be cloned (if at all). By default, a shallow copy is done versus a deep copy.

If an attempt is made to clone an object that is not cloneable, then the CloneNotSupportedException exception is thrown. This is a checked exception; therefore, it must be caught.

It is common for cloneable classes to override clone() so as to make it public rather than protected.

   The Population class extends class X (which is cloneable), and it
   contains numerous primitive types and a bunch of object references:

      try {
         Population p = (Population)super.clone();
         p.name = new String(getName());
         p.growthRate = (GrowthRate)growthRate.clone();
         p.density = (Density)density.clone();
         return p;
      } catch (CloneNotSupportedException e) { return null; }

From the CoreJava book.

Why clone? You never want to return a mutable object as the value of a method because this violates encapsulation. As a rule of thumb, always use clone whenever you need to return a copy of a mutable data field.

When you start dealing with objects instantiated from classes that you do not know well, then how they clone becomes an unknown.

Here is an example of a program that will result in the throwing of a CloneNotSupportedException.

   class A {
      int a;
      public A (int i) { a = i; }
      public Object clone() throws CloneNotSupportedException {
         return super.clone();
   public class Main {
      public static void main(String[] arg) {
         A a1 = new A(260);
         try {
            A a2 = (A)(a1.clone());
         } catch (CloneNotSupportedException e) {}

      The execeptions occurs because class A calls Object.clone(),
      but it does not implement the  cloneable  interface.

{TopOfPage} {Oracle.com::API Specification | Tutorial} {Derek Banas Videos} {Data Structure Visualizations}


Recursion is any solution technique in which large problems are solved by reducing them to smaller problems of the same form.

According to multiple sources, the text Thinking Recursively by Eric Roberts (John Wiley 1986) is an excellent resource on recursion.

Internally, recursive functions are supported using a stack.

Almost every recursive function has the same basic structure:

   if (test for simple case)
      return (simple solution computed w/o using recursion)
      return (recursive solution involving a call to the same function)

A recursive function is a function that calls itself in its function body. The call uses different arguments that ultimately read values that allow the function to return a result.

A recursive algorithm must have a well-defined stopping state, or termination condition.

Tail recursion is when the only recursive call appears in the function and that recursive call is the last operation performed at that procedural level. Typically, tail recursive functions can be easily rewritten as non-recursive functions. The traverse linked-list example provides an example of tail recursion.

Some final comments:

Interesting Recursion Related Tidbit

Headline: "Microsoft's Java JIT compiler bungles tail recursion."

A programmer from England has discovered a flaw in Microsoft's Java environment running in Internet Explorer under Windows. On 10/20/1998 Andrew Kennedy posted a note to Java programming newsgroups showing that jview, Microsoft's command-line interface to its just-in-time compiler, calculates the factorial of 5 (i.e., 5 * 4 * 3 * 2 * 1 * 0!) to be 16. Kennedy writes:
> Microsoft seem to have confused addition with multiplication. > Such an easy mistake to make.
Followup postings pin down the likely source of the bug as incorrectly handled tail recursion in Microsoft's JIT compiler. Unfortunately there seems to be no way to turn off JIT. Kennedy speculates that this error may be responsible for the failure of a large number of Java applets to run in the IE 4 environment.

The Factorial Example

Computing the factorial of a number is popular example of using recursion.

   Mathematically:  n! = { 1  if n = 0; otherwise,  n * (n-1)! }

To compute n! you must:

  1. remember what  n  is
  2. go compute  (n-1)! 
  3. once  (n-1)!  is computed, multiply by  n  to get the final answer
   To compute (n-1)!, you 1st compute (n-2)!.  Computing (n-2)!
   requires finding (n-3)! and so on.  Eventually we end up at 0!
   and 0! is defined to be the value 1.
   In C:
      printf("%i\n", factorial(4));
      int factorial(int n) {
         if (n == 0) return 1;
         return n * factorial(n -1);

   4 is pushed onto the stack
      3 is pushed onto the stack
         2 is pushed onto the stack
            1 is pushed onto the stack
               0 is pushed onto the stack
               returns 1
            1 * 1 returns 1
         2 * 1 returns 2
      3 * 2 returns 6
   4 * 6 returns 24
See factorial.cpp and Factorial.java.

Recall: When a function is called, EXPRs are evaluated and are passed by value. An implicit argument that is passed to a function is a return address. Function return values, if any, are placed in a secure location from which the calling program may retrieve it.

The Power Example

Raising a number to a power can also be solved recursively.
   Power function:   n**k = { 1  if k is 0; otherwise, n * (n**(k-1)) }
Computing  xn , where  x  is a real number and  n  is a non-negative integer, is called the power function and its calculation is usually accomplished with repeated multiplication:
   xn = x * x * x * ... *x * x

      where  x  multiplied with itself  n  times

   20 = 1
   21 = 2 * 1 = 2
   22 = 2 * 2 = 4
   23 = 2 * 2 * 2 = 8
   24 = 2 * 2 * 2 * 2 = 16
The power function can be implemented as follows:

   power(x, n) = xn = { 1, n = 0 | x * xn-1, n > 0 }

   double power(double x, int n) {
      if (n == 0) return 1;
      return x * power(x, n-1);

See power.cpp and Power.java.

Coverting an Integer to a String

   printd(int n) {
      if (n / 10)
         printd(n / 10);
      putchar(n % 10 + '0');
   150 / 10 -- 15 pushed onto the stack
      15 / 10 -- 1 pushed onto the stack
         1 / 10  
         1 is printed
       5 is printed
   0 is printed
See printld.cpp and PrintLD.java.

{TopOfPage} {Oracle.com::API Specification | Tutorial} {Derek Banas Videos} {Data Structure Visualizations}

Home Previous Next