ListOps.java
import java.util.*; class ListOps { public static void main( String[] args ) { // (A) List animals = new ArrayList(); //List<String> animals = Collections.checkedList(new ArrayList<String>(),String.class); animals.add( "cheetah" ); //(B) animals.add( "lion" ); animals.add( "cat" ); animals.add( "fox" ); animals.add( "cat" ); //duplicate cat //(C) System.out.println( animals ); //cheetah, lion, cat, fox, //cat animals.remove( "lion" ); //(D) System.out.println( animals ); //cheetah, cat, fox, cat animals.add( 0, "lion" ); //(E) System.out.println( animals ); //lion, cheetah, cat, fox, //cat animals.add( 3, "racoon" ); //(F) System.out.println( animals ); //lion, cheetah, cat, //racoon, fox, cat animals.remove(3); //(G) System.out.println( animals ); //lion, cheetah, cat, //fox, cat Collections.sort( animals ); //(H) System.out.println( animals ); //cat, cat, cheetah, //fox, lion //(I) List pets = new LinkedList(); //List<String> pets = Collections.checkedList(new ArrayList<String>(), String.class); pets.add( "cat" ); //(J) pets.add( "dog" ); pets.add( "bird" ); System.out.println( pets ); //cat, dog, bird animals.addAll( 3, pets ); //(K) System.out.println( animals ); //cat, cat, cheetah, //cat, dog, bird, fox, //lion ListIterator iter = animals.listIterator(); //(L) while ( iter.hasNext() ) { //(M) System.out.println( iter.next() ); //(N) } } }
When we compile ListOps.java
, using the
-Xlint option we get the following warnings:
C:\classes\ece538\work\kak05>javac -Xlint ListOps.java ListOps.java:9: warning: [unchecked] unchecked call to add(E) as a member of the raw type java.util.List animals.add( "cheetah" ); //(B) ^ ListOps.java:10: warning: [unchecked] unchecked call to add(E) as a member of th e raw type java.util.List animals.add( "lion" ); ^ ListOps.java:11: warning: [unchecked] unchecked call to add(E) as a member of th e raw type java.util.List animals.add( "cat" ); ^ ListOps.java:12: warning: [unchecked] unchecked call to add(E) as a member of th e raw type java.util.List animals.add( "fox" ); ^ ListOps.java:13: warning: [unchecked] unchecked call to add(E) as a member of th e raw type java.util.List animals.add( "cat" ); //duplicate cat //(C) ^ ListOps.java:20: warning: [unchecked] unchecked call to add(int,E) as a member o f the raw type java.util.List animals.add( 0, "lion" ); //(E) ^ ListOps.java:24: warning: [unchecked] unchecked call to add(int,E) as a member o f the raw type java.util.List animals.add( 3, "racoon" ); //(F) ^ ListOps.java:32: warning: [unchecked] unchecked conversion found : java.util.List required: java.util.ListCollections.sort( animals ); //(H) ^ ListOps.java:32: warning: [unchecked] unchecked method invocation: sort(java. util.List ) in java.util.Collections is applied to (java.util.List) Collections.sort( animals ); //(H) ^ ListOps.java:39: warning: [unchecked] unchecked call to add(E) as a member of th e raw type java.util.List pets.add( "cat" ); //(J) ^ ListOps.java:40: warning: [unchecked] unchecked call to add(E) as a member of th e raw type java.util.List pets.add( "dog" ); ^ ListOps.java:41: warning: [unchecked] unchecked call to add(E) as a member of th e raw type java.util.List pets.add( "bird" ); ^ ListOps.java:44: warning: [unchecked] unchecked call to addAll(int,java.util.Col lection extends E>) as a member of the raw type java.util.List animals.addAll( 3, pets ); //(K) ^ 13 warnings
The generics mechanism in Java provides compile-time (static) type checking, but it is possible to defeat this mechanism with unchecked casts. Usually this is not a problem, as the compiler issues warnings on all such unchecked operations. There are, however, times when static type checking alone is not sufficient. For example, suppose a collection is passed to a third-party library and it is imperative that the library code not corrupt the collection by inserting an element of the wrong type.
Static methods such as Collections.checkedList
returns a dynamically typesafe view of the specified collection. Any
attempt to insert an element of the wrong type will result in an
immediate ClassCastException. Assuming a collection contains
no incorrectly typed elements prior to the time a dynamically typesafe
view is generated, and that all subsequent access to the collection
takes place through the view, it is guaranteed that the
collection cannot contain an incorrectly typed element.
Another use of dynamically typesafe views is debugging. Suppose a program fails with a ClassCastException, indicating that an incorrectly typed element was put into a parameterized collection. Unfortunately, the exception can occur at any time after the erroneous element is inserted, so it typically provides little or no information as to the real source of the problem. If the problem is reproducible, one can quickly determine its source by temporarily modifying the program to wrap the collection with a dynamically typesafe view. For example, this declaration:
List animals = new ArrayList();may be replaced temporarily by this one:
List<String> animals = Collections.checkedList( new ArrayList<String>(),String.class);Running the program again will cause it to fail at the point where an incorrectly typed element is inserted into the collection, clearly identifying the source of the problem. Once the problem is fixed, the modified declaration may be reverted back to the original.
In our case, we can use the substitution (commented in the source code) to eliminate the warning messages. The program itself works fine either way.
C:\classes\ece538\work\kak05>java ListOps [cheetah, lion, cat, fox, cat] [cheetah, cat, fox, cat] [lion, cheetah, cat, fox, cat] [lion, cheetah, cat, racoon, fox, cat] [lion, cheetah, cat, fox, cat] [cat, cat, cheetah, fox, lion] [cat, dog, bird] [cat, cat, cheetah, cat, dog, bird, fox, lion] cat cat cheetah cat dog bird fox lion
Maintained by John Loomis, updated Sun Jan 07 15:18:07 2007