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 h = new Hashtable(); 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.