You may use a generic class without specifying a concrete type like this:
GenericStack stack = new GenericStack(); // raw type
This is roughly equivalent to
GenericStack<Object> stack = new GenericStack<Object>();
A class such as GenericStack used without a type parameter is called a raw type . The use of raw type is allowed in JDK 1.5 for backward compatibility with the earlier versions of JDK. For example, generic type is used in java.lang.Comparable in JDK 1.5, but a lot of code still uses the raw type Comparable , as shown in Listing 21.4 (also see the Max class in §10.4, "Interfaces"):
1 // Max.java: Find a maximum object 2 public class Max { 3 /** Return the maximum between two objects */ 4 public static Comparable max( Comparable o1 , Comparable o2 ) { 5 if ( o1.compareTo(o2) > ) 6 return o1; 7 else 8 return o2; 9 } 10 } |
Comparable o1 and Comparable o2 are raw type declarations. Raw type is unsafe . For example, you may invoke the max method using
Max.max( "Welcome" , 23 ); // 23 is autoboxed into new Integer(23)
This would cause a runtime error because you cannot compare a string with an integer object. The new JDK 1.5 compiler displays a warning on line 5 when compiled with the option “Xlint:unchecked , as shown in Figure 21.5.
A better way to write the max method is to use a generic type, as shown in Listing 21.5.
1 // Max1.java: Find a maximum object 2 public class Max1 { 3 /** Return the maximum between two objects */ 4 public static < E extends Comparable<E>> E max( E o1 , E o2 ) { 5 if ( o1.compareTo(o2) > ) 6 return o1; 7 else 8 return o2; 9 } 10 } |
If you invoke the max method using
Max1.max( "Welcome" , 23 ); // 23 is autoboxed into new Integer(23)
a compilation error will be displayed because two arguments of the max method in Max1 must have the same type (e.g., two strings or two integer objects). Furthermore, the type E must be a subtype of Comparable<E> .
As another example in the following code, you may declare a raw type stack in line 1, assign new GenericStack<String> to it in line 2, and push a string and an integer object to the stack in lines 3 and 4.
1 GenericStack stack; 2 stack = new GenericStack<String>(); 3 stack.push( "Welcome to Java" ); 4 stack.push( new Integer( 2 ));
Line 4 is unsafe because the stack is intended to store strings, but an Integer object is added into the stack. Line 3 should be OK, but the compiler will show warnings on both line 3 and line 4, because it cannot follow the semantic meaning of the program. All the compiler knows is that stack is a raw type and it is unsafe to perform certain operations. Therefore, warnings are displayed to alert potential programs.
Tip
Since raw types are unsafe, this book will not use them from here on. |