user2653926
user2653926

Reputation: 604

Collections.sort no compile time error

What is the difference between Collections.sort(list) and Collections.sort(list,null) I supposed both of them compared elements in the list in their natural order.

So I tried these two codes:

CODE 1:

List<Object> list=Arrays.asList("hello",123);
Collections.sort(list);

CODE 2:

List<Object> list=Arrays.asList("hello",123);
Collections.sort(list,null);

The latter compiles but former doesn't giving the expected compiler error that instances of class Object are not comparable. Why latter does not give compile time error.

EDIT: Based on the comment given below. I understand why latter doesn't give compile time error but on running it throws ClassCastException : String cannot be converted into Integer . How it deduced that runtime objects are String and Integer because what I think

public static sort(List<Object> list)  ---> Since list was of type object
{
// For instances of object in list call the compareTo method 
}

}

Upvotes: 0

Views: 1310

Answers (4)

zapl
zapl

Reputation: 63955

Java's generic types are checked at compile time. If you violate the constraits, you can't even compile. The first method is defined as:

<T extends Comparable<? super T>> void sort(List<T> list)

That requires that the List you use is of a type that extend Comparable, specifically some Comparable<X> where X may be any superclass of T. Sounds complicated but doesn't even matter here (try understanding http://yzaslavs.blogspot.de/2010/07/generics-pecs-principle-step-by-step.html if you're interested in that part). List<Object> does not match the first part already. Object doesn't implement any Comparable. => Compiler says no.

The second one is defined as

<T> void sort(List<T> list, Comparator<? super T> c)

that no longer requires that the type of the List has any special property. Any T will work. The only requirement is that you can provide an implementation of Comparator that is able to sort T or a super type. null is like a joker and fits anything. The compiler will not complain even if using null is probably wrong. You do see the problem at runtime.


The reason for

Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at java.lang.Integer.compareTo(Integer.java:52)
    at java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:290)
    at java.util.ComparableTimSort.sort(ComparableTimSort.java:157)
    at java.util.Arrays.sort(Arrays.java:537)
    at java.util.TimSort.sort(TimSort.java:178)
    at java.util.TimSort.sort(TimSort.java:173)
    at java.util.Arrays.sort(Arrays.java:659)
    at java.util.Collections.sort(Collections.java:217)
    at Main.main(Main.java:9)

is that at "TimSort.java:178" it does

static <T> void  sort(T[] a, int lo, int hi, Comparator<? super T> c) {
    if (c == null) {
        Arrays.sort(a, lo, hi);
        return;
    }

which falls back to natural sorting like your first call would do. However it's just a Object[] array at that point and nothing can guarantee that types are actually comparable. It simply casts the types and that fails depending on your luck & content of the list either in Integer.compareTo( ) or String.compareTo( ) because those methods require their own type.

Upvotes: 2

Kent
Kent

Reputation: 195079

These are two different methods in Collections

//here the elements in list should impl. Comparable
Collections.sort(list) 
//here we need a Comparator object, (null is Comparator obj too)
Collections.sort(list, null)

Now comes to the question of runtime classcast problem.

Java converts your list into array to do the sort in background. If your Comparator is null, java will cast the element to Comparable to do sort. Fortunately, the two elements in your list both (String and Integer) implemented Comparable. so till here no Exception.

You have only two elements (2<7 7 is the insertionsort threshold) in your list, so java just simply do insertion sort. Take the Integer, and call the compareTo() method with your string as parameter. Here java cast the parameter to Integer, so that it can compare. As you've seen, String cannot be cast to Integer, you got that Exception.

Upvotes: 1

Subhrajyoti Majumder
Subhrajyoti Majumder

Reputation: 41200

> what is null?

According to JSL -

There is also a special null type, the type of the expression null, which has no name. Because the null type has no name, it is impossible to declare a variable of the null type or to cast to the null type. The null reference is the only possible value of an expression of null type. The null reference can always be cast to any reference type. In practice, the programmer can ignore the null type and just pretend that null is merely a special literal that can be of any reference type.

As null can be reference of any type so it can be reference of Comparator as well, That is why compiler accepts Collections.sort(list,null);.

Where as Collections.sort(list,new Object()); gives compile time exception.


At the time of comparison check compareTo Method will be called Where in Integer.compareTo method it generate ClassCastException.

Upvotes: 0

user2170172
user2170172

Reputation: 81

There is no difference between these two, Is clearly mentioned in api doc. Refer Collections

Upvotes: 0

Related Questions