Vance Chen

+ Follow
since Dec 29, 2004
Cows and Likes
Total received
In last 30 days
Total given
Total received
Received in last 30 days
Total given
Given in last 30 days
Forums and Threads
Scavenger Hunt
expand Ranch Hand Scavenger Hunt
expand Greenhorn Scavenger Hunt

Recent posts by Vance Chen

Hello Mac fans~

I am interested in knowing how those Java Dev stuffs could be done on a MacBook Pro (I am considering to get one!!!).

Like could we install and run eclipse WTP with Spring, weblogic 8.1, JBoss blah blah blah...etc

I am using windows PC now but I'd really love to switch to a Mac.

How are the application compatibility? for example, Firefox, MSN Messenger/Skype, RealPlayer, Nero Buring ROM, WinRAR, BTBitComet, blah blah blah~

Any feedback would be really appreciated!!!

Thank you all~
15 years ago

I am just curious how many ppl passed / how many ppl took the beta exam?
You said the passing rate is the same as the officail version (so it's 59%), right?

I passed it, even if I left out the last 30 questions with "guess" due to not-proper-time-management

I really did a "slow-start with care" though...
You can use my notes posted in another thread:

It is not a complete reference but you can get some ideas from it.

The generics part is hard.
If you just want to use generics (not writing your own generic class, mehtods), you can skip it.

Others are very useful like: varargs, for-each loop, autoboxing....etc

Anyway, take a look and give me some feedback
Add wildcard capture test methods in section 1.3 Example (Pair).

public static void wildcardArgument( Pair<?, ?> pair ) { wildcardCapture( pair ); }
public static <T, U> void wildcardCapture( Pair <T, U> pair )

and in main()

Pair.wildcardArgument( new Pair<String, Integer>("hello", 3388) ); // wildcard capture

to illustrate wildcard capture
[ March 09, 2005: Message edited by: Vance Chen ]
Hi, you are definitely right.

The following code only gives compile warning:
List l = new ArrayList<String>(); // for backwards compatibility

// but I don't think I said it's a compile time error in my notes??? //

Anyway, thanks~
Sorry, maybe my format is a little bit confusing...
I mean the following:

Collection<?> c = new ArrayList<String>(); // it is ok

c.add(new Object()); // compile time error, add Object to collection of unknown

c.add(null); // it is ok

and your code:

Collection<Object> c = new ArrayList<String>();

does give me a compile time error:

found : java.util.ArrayList<java.lang.String>
required: java.util.Collection<java.lang.Object>

Collection<Object> c = new ArrayList<String>();
Can somebody give me some simple Examples for using:

1. wildcard capture

2. wildcard subtype bound is used for read only (why?), and

3. wildcard supertype bound is used for write only (why?)

Thank you so much!!!
Hi all,

I am a newbie of Java and this forum.
This is the note I took for preparing the SCJP 5.0.
I am not sure if it is appropriate to post such an article like this here.
(if not please let me know and delete it)
However, I do hope it is helpful to all of you.

Please let me know if there are any errors/misunderstanding, typos, comments...etc in this note.

Vance's Simple J2SE 5.0 Tiger Notes

Author: Vance Chen
Version: 1.0
Date: 03/09/20005

You can legally use/forward/post this note anywhere you want,
but please keep this header included.

I. Generics

1.1 Subtyping

In general, if Foo is a subtype (subclass or subinterface) of Bar,
and G is some generic type declaration,
it is NOT the case that G<Foo> is a subtype of G<Bar>.


// compile time error
ArrayList<Number> numArray = new ArrayList<Integer>();

1.2 Wildcard Type

Collection<?> is the supertype of all kinds of collections
(pronounced �collection of unknown�).
It is a collection whose element type matches anything.

void printCollection(Collection<?> c)
for (Object o : c) { System.out.println(o); }

In this case, since we don�t know what the element type of c stands for,
we cannot add objects into the collection c,
and only can assign the return value (from the for-each loop iterator)to an Object.
However, we can add "null" into the collection.


Collection<?> c = new ArrayList<String>();
// compile time error, add Object to collection of unknown
c.add(new Object());
// ok

In the following, drawAll() will accept lists of any subclass of Shape,
so we can now call it on a List<Circle> or List<Rectangle> if we want.
Similar, it is not legal to write into shapes in the body of the method.

public class Circle extends Shape { ... }
public class Rectangle extends Shape { ... }

public void drawAll( List<? extends Shape> shapes ) { ... }

public void addCircle( List<? extends Shape> shapes )
// compile time error, add Circle to list of unknown
shapes.add(0, new Circle());

Wildcards can be used outside of method signatures,
as the types of fields, local variables and arrays.

static List<List<? extends Shape>> drawHistory = new ArrayList<List<? extends Shape>>();

public void drawAll( List<? extends Shape> shapes )
// ok, add list of unknown which extends Shape
// to list of list of unknown which extends Shape
for (Shape s: shapes) { s.draw(this); }


Supertype bounds for wildcard

Generally, wildcards with supertype bounds (or lower bounds) let you write
to a generic object and wildcards with subtype bounds (upper bounds) let you
read from a generic object.

Another use:

public interface Comparable<T> { public int compareTo(T other); }
public static <T extends Comparable<? super T>> T minMax(T[] array) { ... }

GregorianCalendar extends Calendar which implements Comparable<Calendar>


Wildcard Capture

(see the Example in section 1.3 below)

public static void wildcardArgument( Pair<?, ?> pair ) { wildcardCapture( pair ); }
public static <T, U> void wildcardCapture( Pair <T, U> pair ) { ... }

1.3 Generic Class and Generic Method

Example: (only for illustration purpose, so not a robust/error checking code)

import java.util.*;

public class Pair <T, U> {

public Pair() { first = null; second = null; }
public Pair(T first, U second) { this.first = first; this.second = second; }

public T getFirst() { return first; }
public U getSecond() { return second; }

public void setFirst( T newValue ) { first = newValue; }
public void setSecond( U newValue ) { second = newValue; }

private T first;
private U second;

// wildcard type used to declare a List
private List<List<? extends Pair>> pairList = new ArrayList<List<? extends Pair>>();

// static generic method
public static <T> T getSomething(T[] a) { return a[a.length - 1]; }

// generic method within a generic class
public <E> E getSomething2(E[] a, T b) { return a[a.length - 2]; }
public <E> T getSomething3(E[] a, T b) { return new Pair<T, U>().getFirst(); }

// wildcard type used to declare a method
public Pair<U, ?> getSomething4() { return new Pair<U, T>(); }

// wildcard capture test
public static void wildcardArgument( Pair<?, ?> pair ) { wildcardCapture( pair ); }
public static <T, U> void wildcardCapture( Pair <T, U> pair )

// generic method main()
public static <S, P> void main(String... args)
Pair<S,P>[] array = new Pair[10]; // compile time warning
//List<T>[] y = new List[10]; cannot reference type variable T in static method
// S z = new S[10]; compile time error

Pair<String, Object> p = new Pair<String, Object>();

Integer i = p.<Integer>getSomething(new Integer[10]); // call static generic method
Float f = p.getSomething2(new Float[10], "hello"); // call generic method
String s = p.getSomething3(new Double[10], "hello"); // call generic method
Pair p2 = p.getSomething4(); // ok
Pair<Object, ?> p3 = p.getSomething4(); // ok
// Pair<Object, String> p4 = p.getSomething4(); // compile time error, incompatible type

Pair.wildcardArgument( new Pair<String, Integer>("hello", 3388) ); // wildcard capture

for (final Pair q1 : array); // can use final modifier in the for-each loop
for (Pair<S, P> q2 : array);
for (Pair<?, ?> q3 : array);

1. We have one or more type variables after the class name (in this case T and U).
T and U can be the same type.

2. The type variable <T> in front of the static method getSomething() is required.
Otherwise the compiler will complain "non-static class T cannot be referenced from a static context".
Here, the type variable <T> is not the same with or related to the one in the class definition.
So you can have Pair<String, Object> and call Pair.getSomething(new Integer[10]);

3. Similar, the type variable <E> in front of the method getSomething3()
has nothing to do with the one in front of the method getSomething2().
However, the type variable T in both getSomething2() and getSomething3()
refers to the one in the class definition (in the above example, String).
So you can call p.getSomething2(new Float[10], "Hello Pair");
and p.getSomething3(new Double[10], "Hello Pair Again");


The type variable must be inserted after the modifiers and before the return type.
We can call the following method with any kind of collection
whose element type is a supertype of the element type of the array.

Generic methods allow type parameters to be used to express dependencies among
the types of one or more arguments to a method and/or its return type.


public static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
for (T o : a) { c.add(o); }

Object[] oa = new Object[10];
Collection<Object> co = new ArrayList<Object>();
fromArrayToCollection(oa, co); // T inferred to be Object

String[] sa = new String[10];
Collection<String> cs = new ArrayList<String>();
fromArrayToCollection(sa, cs); // T inferred to be String
fromArrayToCollection(sa, co); // T inferred to be Object

Integer[] ia = new Integer[10];
Float[] fa = new Float[10];
Number[] na = new Number[10];
Collection<Number> cn = new ArrayList<Number>();
fromArrayToCollection(ia, cn); // T inferred to be Number
fromArrayToCollection(fa, cn); // T inferred to be Number
fromArrayToCollection(na, cn); // T inferred to be Number
fromArrayToCollection(na, co); // T inferred to be Object
fromArrayToCollection(na, cs); // compile time error


Type parameter with bounds

Both T and the bounding type can be either a class or an interface.
Use "&" to separate the bounding types.
We can have as many interface supertypes as we like but
at most one of the bounds can be a class.
If we have a class as a bound, it must be the first one in the bounding list.

public static <T extends Thread & Comparable & Cloneable> Pair<T, U> minMax(T[] a) { ... }


Use wildcard type and type parameter at the same time.

class Collections
public static <T> void copy( List<T> dest, List<? extends T> src ){ ... }


Type Erasure

There are no generics in the virtual machines, only ordinary classes and methods.
When you define a generic type, a corresponding "raw" type is automatically provided.
The name of the raw type is simply the name of the generic type with the type variables removed.
The raw type replaces type variables with the first bound or Object if no bounds are given.
The compiler translates the method call into a call to the raw method and then a cast of the return type.
Casts are also inserted when you access a generic field.

1.4 Legacy Code


JSlider in standard API
void setLabelTable(Dictionary table);
Dictionary getLabelTable();

Dictionary<Integer, Component> labelTable = new Hashtable<Integer, Component>();
labelTable.put(0, new JLabel("A"));
JSlider slider = new JSlider();

// ok

// compile time warning
Dictionary<Integer, Component> labelTable2 = slider.getLabelTable();

1.5 Characteristics and Limitation

1. All instances of a generic class have the same run-time class,
regardless of their actual type parameters.


ArrayList as = new ArrayList<String>();
ArrayList<String> as2 = (ArrayList<String>) as; // compile time warning

if (as instanceof ArrayList<String>) ; // illegal generic type for instanceof

Collection<String> cs = new ArrayList<String>();
if (cs instanceof Collection); // ok

// compile time warning, found: java.lang.Object, required: T
<T> T badCast(T t, Object o) {return (T) o; }

ArrayList<String> as = new ArrayList<String>();
ArrayList<Object> as2 = new ArrayList<Object>();
if ( as.getClass() == as2.getClass() ) // true

2. No primitive types: Only Pair<Integer, Float>, no Pair<int, float> due to type erasure.

3. It is illegal to refer to the type parameters of a type declaration
in a static method or initializer, or in the declaration or initializer of a static variable.

public class ABC <T>
public static T getDEF{return DEF;} // not allowed
private static T DEF // not allowed

4. Generic class cannot extend Throwable. You cannot use a type parameter in a catch clause.

class GenericException<T> extends Exception{} // compile time error

<T> void genericCatch
{ // ...
catch(T e) // compile time error
{ ... }

However, it is ok to use type parameter in exception specifications.

public <E extends Throwable> genericThrows(E a, T b) throws E { ... } // ok

5. Cannot instantiate generic types.

public <E> E getSomething2(E[] a, T b) { T c = b; return a[a.length - 2]; } // ok
public <E> E getSomething2(E[] a, T b) { T c = new T(); return a[a.length - 2]; } // compile time error

public <E> E getSomething2(E[] a, T b) { E[] e = a; return a[a.length - 2]; } // ok
public <E> E getSomething2(E[] a, T b) { E[] e = new E[10]; return a[a.length - 2]; } // compile time error

6. Generic array creation is not allowed.
The component type of an array object may not be a type variable or a parameterized type,
unless it is an (unbounded) wildcard type.

Pair<String, Object>[] array = new Pair<String, Object>[10]; // compile time error
Pair<String, String>[] array = new Pair[10]; // ok
Object[] oa = array;
oa[0] = new Pair<Object, Object>(new Integer(0), new Integer(0)); // ok

Example 1

List<String>[] lsa = new List<String>[10]; // not really allowed
Object o = lsa;
Object[] oa = (Object[]) o;

List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));

List li2 = new ArrayList<Integer>(); // compile time warning
li2.add("abc"); // ok

Example 2

List<?>[] lsa = new List<?>[10]; // ok, array of unbounded wildcard type
Object o = lsa;
Object[] oa = (Object[]) o;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
oa[1] = li;

// compile time error, incompatible type found, found: java.lang.Object required: java.lang.String
String s2 = lsa[1].get(0);
String s1 = (String) lsa[1].get(0); // run time error, ClassCastException

Example 3

List<String>[] ls = new List<?>[10]; // compile time error, incompatible type
List<S>[] ls2 = new List<?>[10]; // compile time error, incompatible type
List<S>[] ls3 = new List[10]; // compile time warning
List<S extends Pair>[] ls4 = new List[10]; // compile time error
List<? extends Pair>[] ls5 = new List<?>[10]; // compile time error
List<? extends Pair>[] ls6 = new List[10]; // compile time warning

1.6 Inheritance

To support translation by erasure, there is a restriction that a class or type variable
may not at the same time be a subtype of two interface types which are different parameterizations
of the same interface. The following is illegal because GregorianCalendar would then implement
both Comparable<Calendar> and Comparable<GregorianCalendar> which are different parameterizations
of the same interface.

class Calendar implements Comparable<Calendar> { ... }
class GregorianCalendar extends Calendar implements Comparable<GregorianCalendar> { ... }

However, the non-generic version is legal.

class Calendar implements Comparable { ... }
class GregorianCalendar extends Calendar implements Comparable { ... }

Example 1

class subPair extends Pair<Integer, Float> { ... }

// compile time error, subPair does not take parameters
Pair<String, Object> sp1 = new subPair<Integer, String>();

Pair<String, Object> sp2 = new subPair(); // compile time error, incompatible type
Pair<Integer, Float> sp3 = new subPair(); // ok
Pair<?, ?> sp4 = new subPair(); // ok

Example 2

class subPair<Integer, Float> extends Pair<Integer, String> { ... }

Pair<String, Object> sp = new subPair<String, Object>(); // compile time error
Pair<Integer, String> sp = new subPair<Integer, Float>(); // ok

class subPair<Integer, Float> extends Pair<Integer, Float> { ... }
Pair<String, Object> sp = new subPair<String, Object>(); // ok

class subPair<T, U> extends Pair<T, U> { ... }
Pair<String, Object> sp = new subPair<Object, String>(); // compile time error

class subPair<U, T> extends Pair<T, U> { ... }
Pair<String, Object> sp = new subPair<Object, String>(); // ok

1.7 Method Overriding

1. If we put the following method in the Pair class (defined above), it is a compile time error

public boolean equals(T value){return true;}

name clash: equals(T) in Pair<T,U> and equals(java.lang.Object) in java.lang.Object
have the same erasure, yet neither overrides the other public class Pair <T, U> {

2. When type erasure interferes with method overriding and polymorphism,
the compiler generates "bridge methods".
The synthesized bridge method is actually called
which then calls the newly defined method to preserve polymorphism.

class Interval extends Pair<Date, Date>
public void setSecond(Date second) { ... }
public Date getSecond() { ... }

The compiler will generate the bridge method in the Interval class:

public void setSecond(Object second) { setSecond((Date) second);}

Similar, in the erased type, there are two getSecond methods:
Date getSecond() // defined in Interval
Object getSecond() // defined in Pair

Note you could not write Java code like this, but the compiler can produce
byte codes for two methods that differ only in their return type.

II. For-Each Loop

for (declaration : expression)

is translated to:

1. if expression is an object that implements the java.lang.Iterable interface
for ( Iterator<E> #i = (expression).iterator(); #i.hasNext(); )
declaration =;

2. if expression is an array of type T
T[] #a = expression;


for (int #i = 0; #i < #a.length; #i++)
declaration = #a[ #i ];

You can add a "final" keyword in the declaration part.
The type of the array or Iterable elements must be assignable to
the loop variable in the declaration.
You cannot use a variable declared outside the for-each loop
as a loop variable (not like the traditional loop).
The loop variable (or iterator) in the for-each loop is hidden from us.
There is no way for backward iteration.

You cannot use for-each loop for:

static void removeSomething(Collection<String> c) {
for ( Iterator<String> i = c.iterator(); i.hasNext(); )
if ( == 4)

The program needs access to the iterator in order to remove the current element.
The for-each loop hides the iterator, so you cannot call remove().
Therefore, the for-each loop is not usable for filtering.
Similarly it is not usable for loops where you need to replace elements
in a list or array as you traverse it.
It is not usable for loops that must iterate over multiple collections in parallel as well.
Finally, using a traditional for loop with get() method
has better performance than using a for-each loop with the iterator.

III. Autoboxing and Unboxing

An Integer expression can have a null value.
If your program tries to autounbox null, it will throw a NullPointerException.
The == operator performs reference identity comparisons on Integer expressions and
value equality comparisons on int expressions.
Finally, there are performance costs associated with boxing and unboxing,
even if it is done automatically.
So, it is not appropriate to use autoboxing and unboxing for scientific computing,
or other performance-sensitive numerical code.
An Integer is not a substitute for an int;
autoboxing and unboxing blur the distinction between primitive types and reference types,
but they do not eliminate it.


Integer i = (Integer)32; // can do explicitly boxing
int j = 34;
i = j;
j = --i; // wrapper type increment/decrement
System.out.println(i > 32); // wrapper type comparison

Number n = 3.0f; // autobox to Float first

int k = new Integer(99);
Integer l = null;
k = l; // runtime error, NullPointerException

Primitives are boxed up to wrapper types in equality comparisons.
For operators such as <, >= and so forth, the wrapper types are unboxed to primitive types.

Boolean values, byte values, short and int values between -128 and 127 and char value < 127
are boxed into the same immutable wrapper objects.

Integer ii = 28;
Integer jj = 28;
System.out.println(ii == jj); // true

Integer ii = 28;
Integer jj = new Integer(28);
System.out.println(ii == jj); // false

Integer ii = 356;
Integer jj = 356;
System.out.println(ii == jj); // false

Integer ii = 356;
int jj = 356;
System.out.println(ii == jj); // true

Float ii = 356.1f;
Integer jj = 356;
Boolean bb = false;
// compile time error, return type of the expression is float (not box to Float)
int kk = (bb) ? ii : jj;

int[] intArray = new int[]{1, new Integer(3)}; // ok
Integer[] integerArray = new Integer[]{256, -33}; // ok

Method resolution will always select the same method that would have been selected in Java 1.4
As the result, foo(double num) will be called in the following code.
public void foo(double num);
public void foo(Integer num);
int bar = 13;

Method resolution rule:
1. The compiler attempts to locate the correct method without any boxing, unboxing, or vararg invocations.
This will find any method that would have been invoked under Java 1.4
2. If the first pass fails, the compiler tries method resolution allowing boxing and unboxing but not vararg.
3. If the second pass fails, the compiler tries method resolution allowing boxing, unboxing and vararg.

IV. Vararg

public static void tryVararg(Integer number, String... arguments);

The three periods after the final parameter's type indicate that
the final argument may be passed as an array (String[] in the above example) or
as a sequence of arguments ("zero" or more String).
You can use only one ellipsis per method and it must appear as the last argument to a method.
Because vararg is nothing more than a regular array,
if you want to iterate each element of the vararg array,
simply just use for-each loop or if you want some arbitrary element, you can use array index directly.
However, you have to be careful for java.lang.ArrayIndexOutOfBoundsException and
you can not something like the following at the same time:

public static void tryVararg(Integer number, String... arguments); // same as below
public static void tryVararg(Integer number, String[] arguments); // compile time error, already defined

If you don't pass anything to the vararg argument, it is still an array (not "null") with length zero.
So sometimes you need error checking for the zero-length array.

tryVararg(new Integer(1), "a", "b", "c") // ok
tryVararg(38, new String[] {"a", "b", "c"}) // ok
tryVararg(38) // ok

As a client, you should take advantage of them whenever the API offers them.
Important uses in core APIs include reflection, message formatting, and
the new printf facility. As an API designer, you should use them sparingly,
only when the benefit is truly compelling. Generally speaking,
you should not overload a varargs method, or it will be difficult for programmers to
figure out which overloading gets called.

Note: you can have public static void main(String... args) { ... } as your main method

V. Static Import

The static import declaration is analogous to the normal import declaration.
Where the normal import declaration imports classes from packages,
allowing them to be used without package qualification,
the static import declaration imports static members (classes, enums, variables, methods)
from classes, allowing them to be used without class qualification.
Only use it when you'd otherwise be tempted to declare local copies of constants,
or to abuse inheritance (the Constant Interface Antipattern).

import static java.lang.Character.Subset; // static nested class
import static java.lang.System.out; // static member
import static java.lang.Math.*; // static member and methods
import static java.lang.System.out.println; // compile time error, println() is an instance method

Example 1


public class Outer {
public enum Inner { X, Y, Z };

import static*;

Example 2

// compile time error
import java.util.Date;
import java.sql.Date;

// ok with import
import java.util.*;
import java.sql.*;

Date today; // compile time error here

// ok with static import
import static java.util.Arrays.sort;
import static java.util.Collections.sort;
import static;

sort(intArray); // compile time error here

VI. Formatter

StringBuilder sb = new StringBuilder();
Formatter formatter = new Formatter(sb, Locale.FRANCE);
formatter.format("Format %d", "String"); // java.util.IllegalFormatConversionException
formatter.format("%d"); // java.util.MissingFormatArgumentException:
System.out.println(sb.toString()); // output the formatted string

String newString = String.format( ... ); // static method in String class
System.out.format( ... ); // same as below
System.out.printf( ... ); // same as above


1. Type

For %b and %B, except for boolean/Boolean type, any non-null values is true, while null values are false
For %c and %C, supplied value must be a byte, short, char, or int (or their wrapper type)
For %d, only integer types allowed (or BigInteger), no character types
For %h and %H, formats the value as hexadecimal representation of the value's hashcode
For %s and %S, formatTo() is called if Formattable interface is implemented
otherwise toString() is called on the object
For %t[a...Z] and %T[a...Z], requires a Date, Calendar, or long argument

2. Precision

For %e, %E, and %f, the default precision is 6
For %g, %G, the precision is the total number of significant digits to be displayed
For %s, %h, %b, the precision determines the maximum characters output

Specify precision for other conversion types can result in an exception at runtime.
Trailing zeros are added as needed.

3. Argument
Use < to reuse the previous argument and use [the ith argument]$ to refer to the ith argument in the list

4. Object[] array = new String[] {"You","Me","?"};
System.out.printf("what about %s", array); // only You...

VII. Enum

Enums are classes extending the java.lang.Enum class.
You can declare an enum as public with the same name in a .java file or
you can declare it inside a class.
Nested enums are implicitly static, but static modifier can still be used in this case.
The enum type is final so it is not extensible.
However, you cannot use the final modifier in the enum declaration.
You cannot have public constructors for enums and they are implicitly private.
Each declared value is an instance of the enum class itself.
The values are public, static, and final, so they can be compared with == or equals().
Enum constants are only comparable (use the compareTo() method) to other enum constants
of the same enum type. The natural order implemented by this method is the order in which
the constants are declared.
Enums have toString(), a static method valueOf(), and a final method ordinal().


enum Season implements Code{ // enum can implement interface

SPRING(0){public void doSomething(){System.out.println("It's Spring!");}},
SUMMER(1){public void doSomething(){System.out.println("It's Summer!");}},
FALL(2){public void doSomething(){System.out.println("It's Fall!");}},
WINTER(3){public void doSomething(){System.out.println("It's Winter!");}};

private Season(int code){this.code = code;} // private constructor
public int getCode() { return code; }

public abstract void doSomething(); // value-specific class body

private int code;

interface Code { public int getCode(); }

for(Season s : Season.values()) {



Season now = Enum.valueOf(Season.class, "SPRING");

It is illegal to have the enum name prefix to the case label and you cannot mix the integer types
and enum type constants for either switch arguments or case labels.

switch(Season.SPRING) // if we pass an int, it is a compile time error
//case Season.SPRING:System.out.println(Season.SPRING); break; // compile time error
case SUMMER:System.out.println(Season.SUMMER); break;
case FALL: System.out.println(Season.FALL); break;
case WINTER:System.out.println(Season.WINTER); break;
default:System.out.println(Season.SPRING); break;

Now you can have EnumMap and EnumSet for the enum types you defined.

EnumMap<Season, String> seasons = new EnumMap<Season, String>(Season.class);
EnumSet seasons = EnumSet.allOf(Season.class);

VIII. Reference
1. Core Java 2 Vol. I 7th edition by Cay S. Horstmann and Gary Cornell
2. Java 1.5 Tiger A Developer's Notebook by Brett Mclaughlin and David Flanagan
3. Generics in the Java Programming Language by Gilad Bracha

[ March 09, 2005: Message edited by: Vance Chen ]

[ March 09, 2005: Message edited by: Vance Chen ]

[ March 09, 2005: Message edited by: Vance Chen ]

[ March 09, 2005: Message edited by: Vance Chen ]

[ March 09, 2005: Message edited by: Vance Chen ]
[ March 09, 2005: Message edited by: Vance Chen ]
As my understanding, if only talk about keys and values:

For Hashtable class, neither the key nor the value can be null. The HashMap class is roughly equivalent to Hashtable, except that it is unsynchronized and permits null value"s" and only one null key. WeekHashMap class can have null values and null key as HashMap.

Could someone explain more about "weak key/reference"? Thanks!