unimportant logo identifying Barry Cornelius

University of Oxford

Computing Services

Teaching a Course on Understanding Java

  Author: Barry Cornelius Date: 24th January 2000

Contents

1. Abstract

The main aim of this paper is to explain the rationale behind the design of a course that is an introduction to programming using Java. One of the key features of this course is the early introduction of interfaces. The paper explains why it is appropriate to do this. The paper also points out some of the deficiencies in the design of classes that are made by textbooks that are targetted at this kind of course.

2. Introduction

3. The order in which to teach things

During the last 25 years, I've been involved on a number of occasions with switching the first programming language.

University of Hull      Algol 60    Pascal
University of Durham    Pascal      Modula-2
University of Durham    Modula-2    Java
Every time you find yourself with a lot of new ideas to teach. And I find it exciting to sit down and think about what order to teach the various ideas.

Using Pascal/Modula-2, the topics that I have taught included:

terminal I/O
expressions
if statement
for statement
case statement
while statement
arrays
procedures and functions
recursion
records
pointers
linked lists
stacks 
queues
trees

When moving to Java, procedures and functions are called methods, and pointers, linked lists, stacks, queues and trees are replaced by other things.

Here is a list of some of the new ideas of Java:

creating an object
using an instance method
using a class method
using the wrapper types (Integer, Double, etc)
declaring a class type
declaring a method declaration
declaring an interface
implementing a Core API interface
implementing one of your own interfaces
implementation inheritance from a Core API class
implementation inheritance from one of your own classes
creating a window
adding buttons to a window
using a textfield for input/output
providing menus
using MVC to design programs
using the Collection API: lists, queues, stacks
using the Collection API: sets
using the Collection API: maps
using a throws clause
using a try statement
declaring an exception class
using applets

Those are some of the topics that I teach, but of course there are many more that could be taught. The order in which the parts of Java are taught in this course is given in the Appendix to this paper.

4. Introducing objects early?

If primitive types have to be taught reasonably early, how do we teach both primitive types and class types? My own view is that they can be taught in the following order:

  1. introduce primitive types;
  2. demonstrate that operations can be performed on values of a primitive type by using methods (and operators);
  3. point out that the primitive types are not sufficient to represent real-world objects;
  4. introduce some of the class types of Java's Core APIs as a way of representing other real-world objects.
During this process it is important to use the WWW pages that document Java's Core APIs in order to show what is possible with these class types.

So, although some may argue that my course is not an object-first course:

5. Handling control statements and method declarations

So in this course, the following order is used to teach the bread-and-butter topics:

I'm not ashamed that you will find these taught in this order in many books that are teaching a language other than Java.

6. Interfaces and classes

  1. The role of interfaces and classes
  2. Supporters of the use of interfaces
  3. Non-supporters of the use of interfaces

6.1. The role of interfaces and classes

Both Ada and Modula-2 separate out the interface from the implementation:

Ada         package specification    package body
Modula-2    definition module        implementation module
Although a similar idea can be achieved in C++, it is not so cleanly done. In Java, interfaces can be used:
Java        interface declaration    class declaration

public interface Date;
{
   public int getDay();
   ...
   public void setDay(int pDay);
   ...
}

public class DateImpl implements Date
{
   private int iYear;
   private int iMonth;
   private int iDay;
   ...
   public int getDay()
   {
      return iDay;
   }
   ...
   public void setDay(final int pDay)
   {
      iDay = pDay;
   }
   ...
}

The lectures stress that code should be written in terms of the interface and that the name of the class should only be used when you want to create an object (of the class that implements the interface):

Date tTodaysDate = new DateImpl(2000, 1, 24);
...
private static boolean iIsLeap(final Date pDate)
{
   final int tYear = pDate.getYear();
   return (tYear%400==0) || (tYear%4==0 && tYear%100!=0);
}

The course points out that:

6.2. Supporters of the use of interfaces

'Design Patterns: Elements of Reusable Object-Oriented Software'
Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides
‘This ... leads to the following principle of reusable object-oriented design: Program to an interface, not an implementation. Don't declare variables to be instances of particular concrete classes. Instead, commit only to an interface defined by an abstract class [or an interface in Java]. You will find this to be a common theme of the design patterns in this book.’

Another book that covers similar material is 'Patterns in Java: Volume 1' by Mark Grand.

'UML Distilled'
Martin Fowler

‘One of the great qualities of object-oriented development is that you can vary the interfaces of classes independent of the implementation. Much of the power of object development comes from this property. However, few people make good use of it. Programming languages use a single construct, the class, which contains both interface and implementation. When you subclass, you inherit both. Using the interface as a separate construct is rarely used, which is a shame.’

'ChiMu OO and Java Development: Guidelines and Resources'
ChiMu Corporation

‘Use interfaces as the glue throughout your code instead of classes: define interfaces to describe the exterior of objects (i.e., their Type) and type all variables, parameters, and return values to interfaces. The most important reason to do this is that interfaces focus on the client's needs: interfaces define what functionality a client will receive from an Object without coupling the client to the Object's implementation. This is one of the core concepts to OO.’
http://www.chimu.com/publications/javaStandards/

6.3. Non-supporters of the use of interfaces

In an informal analysis of when specific aspects of Java are taught by various books, I obtained the following results. When a result appears as n:p, n gives the page number and p gives the page number expressed as a percentage. So the percentage figure gives a measure of how far through the book the aspect is taught.

  Arnow  Bishop    Deitel  Garside  Horstmann  Koffman   Lewis   Smith Cornelius
How many pages are in the main part of the text?  How many in all?
725,805 479,508 1228,1344  609,660    569,624  683,824 559,857 433,474 ?470,?500
When is the user-declared class introduced?
  90:12   80:17    326:27   170:28     324:57    56:08  140:25   66:15    206:44
When are interfaces introduced?
 659:91  269:56    427:35   347:57         no   440:64  338:60  269:62    223:47

7. Minimal public interfaces

  1. What is meant by minimal public interface?
  2. The need to provide equals and hashCode
  3. The need to provide a cloning operation
  4. The need to provide compareTo
  5. Supporters of minimal public interfaces
  6. Non-supporters of minimal public interfaces

7.1. What is meant by minimal public interface?

When teaching interfaces and classes, I stress that it is important that each interface-class has:

7.2. The need to provide equals and hashCode

Most books do not provide each class with the ability to find out whether two objects of the class have the same value.

public boolean equals(Date pDate)
{
   return iYear==pDate.iYear &&
          iMonth==pDate.iMonth && iDay==pDate.iDay;
}
If a client attempts to use objects of this class with objects of the Collections API (or Hashtable or Vector), they are in for a shock. None of the following methods will work with that declaration of equals:
Hashtable contains, containsKey, get, put, remove
Vector contains, indexOf
List contains, remove, indexOf
Map containsKey, containsValue, get, put, remove
Set add, contains, remove

Instead, you need to teach that for the equals method to be useful it needs to have a parameter of type Object. For example, if we are providing an interface called Date and a class called DateImpl, we could declare the following:

public boolean equals(final Object pObject)
{
   if ( ! (pObject instanceof DateImpl) )
   {
      return false;
   }
   return iYear==((DateImpl)pObject).iYear &&
          iMonth==((DateImpl)pObject).iMonth &&
          iDay==((DateImpl)pObject).iDay;
}

If you declare equals properly, you need also to declare hashCode. There are warnings about this in the documentation of some of these classes. For example, the WWW pages that document java.util.Hashtable states that ‘to successfully store and retrieve objects from a hashtable, the objects used as keys must implement the hashCode method and the equals method.’

public int hashCode()
{
   return iYear*416 + iMonth*32 + iDay;
}

The informal analysis of when specific aspects of Java are taught by various books gave the following results:

  Arnow  Bishop    Deitel  Garside  Horstmann  Koffman   Lewis   Smith Cornelius
Does the book suggest that equals always be declared?
   lost      no        no       no     339:60       no    lost    lost    219:47
Does the book teach the proper declaration of equals?
   lost      no        no       no     340:60       no      no   wrong    221:47
Does the book teach the proper declaration of hashCode?
     no      no        no       no         no       no      no  311:72    223:47

7.3. The need to provide a cloning operation

Few books explain that it is desirable for a class to provide a cloning operation.

Date tBirthDate = new DateImpl(2000, 1, 24);
Person tSomePerson = new PersonImpl("Joe", tBirthDate);
Do we share?
public class PersonImpl
{
   private String iName;
   private Date iDateOfBirth;
   public PersonImpl(final String pName,
                     final Date pDateOfBirth)
   {
      iName = pName;
      iDateOfBirth = pDateOfBirth;                // share
      ...
Or do we clone?
      iDateOfBirth = new DateImpl(pDateOfBirth);  // clone
Note that you need not do this copying if the objects of the class (in this case, the class DateImpl) are immutable.

It is best to provide a method called clone as this can be used when inheritance is involved. However, getting the code of a clone method completely right is difficult. See the article by Bill Venners at http://www.artima.com/innerjava/webuscript/cloning.html

Because it is hard to get right, it is also difficult to teach. Instead, I cheat by just providing a constructor that can be used for cloning:

public DateImpl(final Date pDate)
{
   iYear = pDate.getYear();
   iMonth = pDate.getMonth();
   iDay = pDate.getDay(); 
}

7.4. The need to provide compareTo

This interface is simply:
public interface Comparable
{
   public int compareTo(Object pObject);
}

In order for Date and DateImpl to do this, we need to change the header of the interface Date to be:

public interface Date extends Comparable
and to add the following declaration to the class declaration for DateImpl:
public int compareTo(final Object pObject)
{
   DateImpl tDateImpl = (DateImpl)pObject;
   int tResult = iYear - tDateImpl.iYear;
   if (tResult==0) {
      tResult = iMonth - tDateImpl.iMonth;
      if (tResult==0) {
         tResult = iDay - tDateImpl.iDay;
      }
   }
   return tResult;
}

The Comparable interface became part of Java when Java 2 was released in December 1998. Although most of the books that teach Java as a first language were prepared before then, a few have since been updated for Java 2. None of the ones that I've seen discuss the possibility of a class implementing the Comparable interface.

7.5. Supporters of minimal public interfaces

I've nicked the phrase minimal public interface from a book called 'Object-Oriented Design Heuristics' by Arthur Riel. He says: ‘If the classes that a developer designs and implements are to be reused by other developers in other applications, it is often useful to provide a common minimal public interface. This minimal public interface consists of functionality that can be reasonably expected from each and every class.’

Bill Venners has also written an article on the topic of minimal public interfaces. It is entitled 'The canonical object idiom'. You will find it at http://www.javaworld.com/javaworld/jw-10-1998/jw-10-techniques.html

7.6. Non-supporters of minimal public interfaces

I've found no books on teaching Java as a first language that stress the importance of always providing a minimal public interface.

8. A turning point

The previous sections of this paper have described the contents of the first 20 lectures. This is a turning point in the course. Although there are a few important aspects of the Java language that are still to come, most of the important ones have now been introduced. The remaining lectures of the course are mainly concerned with introducing two important APIs: the Swing API and the Collections API.

Although both of these APIs came into being when Java 2 was released, they are both considered by Sun to be part of the Core APIs of Java.

One of the main aims of the second half of the course is to become familiar with these two APIs. They are both quite large: the course's aim is to introduce the basic ideas giving the students sufficient knowledge to look at the other parts of the API on their own.

Note the emphasis in this part of the course is on using the code of existing libraries: by taking a ride on the work of others, Java gives even the beginner the possibility of easily building reasonably powerful pieces of code.

9. The Swing API

The course looks at the Swing API in two takes. In the first take, the students are introduced to the following ideas:

In order to use the Swing API, a programmer is required to be familiar with the idea of declaring a class that implements an interface. In this course, the lectures on the Swing API appears immediately after the lectures that introduce interfaces and classes.

In later lectures, the classes JMenuBox, JMenu and JMenuItem are introduced. These three classes are needed to build a menu system. Because JMenuItems are another form of button, responding to a click of a menu item can be handled in a similar way to that for buttons (which were discussed in earlier lectures).

10. The Collections API

The Collections API provides a useful set of interfaces and classes that can be used for building data structures that represent collections of data. The emphasis in this course is on how to make effective use of this API rather than on how to implement the various data structures.

The course describes and explains the differences between the capabilities of the three main interfaces called List, Set and Map (and subinterfaces called SortedSet and SortedMap), and the six classes called ArrayList, LinkedList, HashSet, TreeSet, HashMap and TreeMap. The use of the Iterator interface is also described.

Once again, the stress is to write the code of clients in terms of the interface, only mentioning the name of a class when you want to create a collection object.

Although later lectures show how to implement the List interface by (a) an array and (b) a doubly linked list, this only appears after extensive use in earlier lectures of the List, Set and Map interfaces.

11. The use of MVC and the Observer pattern

Whilst introducing the Collections API, the course explains and demonstrates the advantages of using the Model-View-Controller pattern to decouple a data structure from any user interface. The simpler form in which the view and the controller are combined (sometimes called Model-UserInterface) is also discussed. By having the class that implements the model derived from java.util.Observable, it is easy to provide multiple views of the model (the class for each view implementing the java.util.Observer interface). These ideas are illustrated by two examples.

The course develops a case study for which different user interfaces are developed and, also, different data structures are used. Both the user interface and the data structure are easily switched because of the use of interfaces and MVC.

12. Implementation inheritance

Often books on Java teach the following topics in one chapter:

These topics are taught in this order because it seems to be an obvious order: first introduce the advantages of deriving classes from base classes; then explain polymorphism (dynamic binding); the explain that an abstract class is a special form of base class; and finally introduce an interface as a special form of an abstract class. However, a chapter that has these topics introduces a lot of new ideas and explaining them all at once will overload the reader.

Although there is some logic to teaching interfaces in this way, it is better to make a clearer separation between implementation inheritance and interfaces. I think it is important to teach interfaces early, and to leave implementation inheritance until later.

Although the lectures on implementation inheritance appears late in this course, some of the basic ideas are introduced in earlier lectures:

It is only towards the end of this course that the students learn how to derive a class from one of their other classes. These lectures also introduce the idea of abstract classes.

13. Applets

Because the full details of implementation inheritance are taught late, the material on applets also appears late. However, because all the ground work has been covered, there is little that needs to be taught about applets: just the role of the init, start, stop and destroy methods.

14. Exceptions

Some books seem to include exceptions as an afterthought: often the whole topic is taught in the last chapter. As with implementation inheritance, my course gradually introduces the various aspects of exceptions:

Although in Java it can be tempting to overuse exceptions, in this course it is recommended that they are only used for untoward situations. For this reason, the idea of introducing your own exceptions is briefly only mentioned at the end of the course. A good article on the topic is Designing with exceptions by Venners. You will find it at http://www.javaworld.com/javaworld/jw-07-1998/jw-07-techniques.html

15. Keyboard input

Often, books that teach Java provide their own package of classes. One reason for doing this is that it makes it easy to provide a class that facilitates the reading of a value of some primitive type from the keyboard.

Although this approach has its advantages, it is also inconvenient for students:

In this course, the horrors of Java's keyboard input are introduced early:

BufferedReader tKeyboard = new BufferedReader(new InputStreamReader(System.in));
String tHeightString = tKeyboard.readHeightString();
double tHeight = Double.parseDouble(tHeightString);
Note the use of both instance methods and class methods and the need to use the wrapper classes of the primitive types.

16. Teaching devices

17. Appendix: the order in which the material is taught

  1. Examining the structure of Java programs
  2. Constructing simple programs
  3. Using objects and classes from Java's Core APIs
  4. Reading values from the keyboard
  5. Using arithmetic expressions to represent formulae
  6. Using if statements to make decisions
  7. Using for statements to repeat statements
  8. Using methods to organize programs
  9. Using other forms of control statements
  10. Reading from and writing to files
  11. Using interfaces and classes to produce new types
  12. Looking at other examples of interfaces and classes
  13. Providing a GUI: buttons and textfields
  14. Manipulating collections: lists, queues and stacks
  15. Decoupling the model from the user interface
  16. Using enumerations, sets and maps
  17. Providing a GUI: menus
  18. Using arrays and implementing the List interface
  19. Deriving a class from another class
  20. Writing applets (for use with the WWW)
  21. Looking briefly at other topics: (a) starting another thread, (b) declaring your own packages, (c) the factory pattern, (d) the JDBC API, (e) client-server computing, (f) generic types, (g) standardization, (h) finding information about Java.

18. References



Date: 24th January 2000 Author: Barry Cornelius.
This page is copyrighted