Lecture 2 -- Key Constructs of Java

In this lecture we will review some of the key constructs of Java
that you will need to know for Assignment 1, and discuss some of
the new features of J2SE 5.0.

Contents

1.  Classes & Objects -- a brief review
2.  Reference vs. Primitive types
3.  Array representation, multidimensional arrays, ragged arrays
4.  Arrays vs. Vectors vs. Hashtables
5.  Command line interface
6.  New features of J2SE 5.0 -- generics, enhanced for, enum
7.  Debugging and experimentation

======================================================================
1.  Classes & Objects -- a brief review

A program usually consists of several classes.  Each
class has some fields and some methods.  A typical class
declaration looks like

class ClassName {

   field declarations;

   method(parameters) {
     local variable declarations;
     body;
   }

   method(parameters) {
     local variable declarations;
     body;
   }
}

The main class has a main method, which is always declared as

    public static void main(String[] args) {
       ... body ...
    }

static fields
  - belong to a class, shared by all objects of the class.
  - declared using keyword "static"
instance fields
  - belong to objects of a class
  - a different one for each object

Example:

class Widget {

    static int nextSerialNumber = 10000;
    int serialNumber;

    Widget() {
        serialNumber = nextSerialNumber++;
    }

    Widget(int sn) {
        serialNumber = sn;
    }

    public static void main(String[] args) {
        Widget a = new Widget();
        Widget b = new Widget();
        Widget c = new Widget();
        Widget d = new Widget(42);
        System.out.println(a.serialNumber);
        System.out.println(b.serialNumber);
        System.out.println(c.serialNumber);
        System.out.println(d.serialNumber);
    }        
}

Methods can be static or instance
  - static methods may not refer to instance fields or instance methods
  - static methods can be called even if no objects of the class have been created

Parameters, local variables of a method
  - exist only while the method is running
  - use parameters to pass input data to a method
  - use local variables for temporary data used in a method
  - use fields for persistent data or data shared by several methods

Reference fields, methods in own class by name
  - serialNumber, nextSerialNumber
Reference static fields in another class by qualified name
  - Widget.nextSerialNumber
Reference fields of objects with object name
  - a.serialNumber
E.g. System.out.println(a.serialNumber)
  - out is a static field in class System
  - value of out is an instance of a class that has a method println(int)

if an object has to refer to itself, use "this"

Overloading: look at String.valueOf(...) in Java API
  - there are 9 of them, one for each of 9 different argument types
  - think of argument types as part of the name of the method

Class hierarchy
  - arranged in a tree -- at the root (top) is Object
  - e.g. String and StringBuilder are subclasses of Object
  - methods and fields of superclass are available in subclass

======================================================================
2.  Reference vs. Primitive types

Primitive types
  - int, long, float, byte, char, boolean, ...
  - take a single word or 2 words of storage
  - not objects in the Java sense
  - variable of that type contains the actual data
Reference types
  - arrays and objects (e.g. String, StringBuffer, Vector)
  - usually take more storage
  - variable of that type contains a POINTER to the actual data
  - null is a reference type

== vs. equals()

use == for primitive types
use == for reference types (e.g. Strings) ONLY if you mean actual
identity of the two objects (note that this is ALMOST NEVER what you want!)
E.g. can have two different strings, both with value "hello"
use equals() instead, e.g. x.equals("hello") instead of x == "hello".

======================================================================
3.  Array representation, multidimensional arrays, ragged arrays

arrays are reference types
elements of arrays can be reference or primitive
  - e.g. int[] or String[]
  - if a is an array, a.length is its length
  - elements are a[0], a[1], ..., a[a.length - 1]

multidimensional arrays are really arrays of arrays
  - e.g. int[][] is an array of integer arrays
  - can be "ragged"; e.g. all the arrays in the 2nd dimension need not be the same length

class MultiArray {
   
   static int[][][] a = new int[2][3][];

   public static void main(String[] args) {
      for (int i = 0; i < a.length; i++) {
         for (int j = 0; j < a[i].length; j++) {
            a[i][j] = new int[i+j];
         }
      }
      for (int i = 0; i < a.length; i++) {
         for (int j = 0; j < a[i].length; j++) {
            System.out.println(a[i][j].length);
         }
      }
   }
}

> java MultiArray
0
1
2
1
2
3


======================================================================
4.  Arrays vs. Vectors vs. Hashtables

Three extremely useful constructs -- see API

array
  - storage is allocated when they are created, cannot change

Vector (in java.util)
  - "extensible" arrays -- can grow as needed
  - can append or insert elements, access i-th element, reset to 0 length
  - can get an enumeration of the elements

Hashtable (in java.util)
  - save data indexed by keys
  - can lookup data by its key
  - can get an enumeration of the elements

E.g. Create a hashtable of numbers, using the names of the numbers as keys:

     Hashtable numbers = new Hashtable();
     numbers.put("one", new Integer(1));
     numbers.put("two", new Integer(2));
     numbers.put("three", new Integer(3));

To retrieve a number:

     Integer n = (Integer)numbers.get("two");
     if (n != null) {
         System.out.println("two = " + n);
     }

Caveat: returns null if does not contain the key
  - need to check in order to avoid null ptr exception

======================================================================
5.  Command line interface

arguments are contained in the String array parameter of the main method

class CmdLineArgs {
   
   public static void main(String[] args) {
      System.out.println(args.length);
      for (int i = 0; i < args.length; i++) {
         System.out.println(args[i]);
      }
   }
}

> java Foo
0
> java Foo asdf zxcv ss
3
asdf
zxcv
ss
> java Foo hello world
2
hello
world
> 

Try your programs in a command window, not just in DrJava, because that's
how we'll be testing them.  Behavior may be a little different.

======================================================================
6.  New features of J2SE 5.0 -- generics, enhanced for, enum

Generics

old:

      Hashtable h = new Hashtable();
      h.put("one",new Integer(1));
      Integer s = (Integer)h.get("one");

new:

      Hashtable<String,Integer> h = new Hashtable<String,Integer>();
      h.put("one",new Integer(1));
      Integer s = h.get("one");

No longer necessary to do a class cast each time you take an element
out of the hashtable.

----------------------------------------------------------------------
Enhanced for

old:

      String[] a = {"hello","world"};
      for (int i = 0; i < a.length; i++) {
         System.out.println(a[i]);
      }

new:

      String[] a = {"hello","world"};
      for (String s : a) {
         System.out.println(s);
      }

----------------------------------------------------------------------
Enum

old:

class Enum1 {
   public static final int WINTER = 0;
   public static final int SPRING = 1;
   public static final int SUMMER = 2;
   public static final int FALL   = 3;
   public static void main(String[] args) {      
      System.out.println(WINTER);
   }
}

> java Foo
0


new:

enum Season { WINTER, SPRING, SUMMER, FALL }

class Enum2 {
   public static void main(String[] args) {      
      System.out.println(Season.WINTER);
   }
}

> java Foo
WINTER

======================================================================
7.  Debugging and experimentation

Don't be afraid to experiment if you don't know how things work.
Debugging -- isolate the bug using print statements, binary search.