Monday, September 13, 2010

Java Generics - Part 4

Wildcards:

 

Consider the a method that prints all the elements of a collection (pre 1.5 code):

 

private static void printCollection(Collection objectCollection)

{

      for (Object element: objectCollection)

      {

            System.out.println( element );

      }

}

 

The above code when invoked as follows:

 

 

printCollection( Arrays.asList( new String[] {"test", "another test"} ) );

 

 

gives the following output:

 

 

test

another test

 

 

Lets write the same method using generics:

 

private static void printCollection(Collection<Object> objectCollection)

{

      for (Object element: objectCollection)

      {

            System.out.println( element );

      }

}

 

But now the same invocation ( printCollection( Arrays.asList( new String[] {"test", "another test"} ) ); ) will lead to a compile time error! :

 

PrintCollection.java:8: printCollection2(java.util.Collection<java.lang.Object>) in PrintCollection cannot be applied to (java.util.List<java.lang.String>)

                 printCollection2( Arrays.asList( new String[] { "test", "another test" }) );

                 ^

1 error

 

This is because when the String[] is converted to a List, it returns a List<String>. And a List<String> is not a List<Object> (although String is a Object. Why? Read this)

 

To resolve this issue, we could use…wildcards as follows:

 

private static void printCollection2(Collection<?> objectCollection)

{

      for (Object element: objectCollection) // compiler error will result for objectCollection.add(anything). Because Collection<?> specifies an unknown element type<terminology>. And the compiler has no way to check the type of “anything” against the unknown type. Null is exception.

      {

            System.out.println( element );

      }

}

 

 

No comments: