Wednesday, December 19, 2007

For Beginners: Java 5 Collections.sort() and Generics

Today at work a co-worker came up with an interesting question related to a warning related to unchecked types when using Collections.sort under Java 5. When moving a project from an earlier JRE to Java 5 this sort of thing happens all the time. Though the answer was really quite simple, sometimes looking at the compiler errors, one isn't quite sure what should be done.

Suppose you tried to compile the following code:
public class Test{
public static void main(String[] args){
ArrayList<Foo> testArr = new ArrayList<Foo>();
Collections.sort(testArr);
}

public class Foo implements Comparable{
public int a = 0;

public int compareTo(Object o){
return 0;
}
}
}
Upon compilation the javac compiler will issue the following warning.
warning: [unchecked] unchecked method invocation: <T>sort(java.util.List<T>) in
java.util.Collections is applied to (java.util.ArrayList<Test.foo>) Collections.sort(test);
Essentially, we are being warned that the version of the Comparable we're using doesn't support the generics, so you had better know what you're doing. The answer is to explicitly tell the compiler what kind of Comparable Foo knows how to compare. Doing this is really quite simple, but it's not immediately obvious from the warning error how the code needs to change.

If we change the inner class to specify what type Comparable operates over, the warnings will go away.
public class Foo implements Comparable<Foo>{
public int a = 0;

public int compareTo(Foo o){
return 0;
}
}
Note that in Java 5 Comparable now carries a type. That is, it's a Comparable<T>. The other important thing to note is that rather than having compareTo take an Object, it should take the specific type that it will compare.

In the office today my co-worker was happy to change his code to make the warning go away, however he did question why the compiler couldn't make some assumptions about the type for Comparable<T>. I'm not a language specialist, but I have a feeling that it has to do with compiler implementation and the limitations of generics as implemented in the byte code. Though it would be fun to learn more about the real theory behind the design decision.

In the mean time, if you run across this simple warning and want to make it go away, it all has to do with making sure that your object is set up correctly with the new Java 5 type paradigm.

1 comment:

Carl van Denzen said...

It has nothing to do with byte code. Byte code knows nothing about generics.