Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Java allow a compare(String, String) Comparator method to take arguments of Object type?

So here is my code:

public class Demo {

    public static final Comparator<String> SORT_BY_LENGTH = new SortByLength();

    private static class SortByLength implements Comparator<String>{
        public int compare(String w, String v) {
            return w.length()-v.length();
        }
    }

    public static void main(String[] args) {
        Object o1 = "abc", o2 = "bc";
        Comparator c = SORT_BY_LENGTH;
        System.out.println(c.compare(o1, o2));//OK, output 1
    }
}

So what confuses me is that the signature of the compare() method takes 2 String variables as argument. However, even when I input 2 arguments of Object type, it still works. Why is that?

PS: if I define some ordinary method as follows, then the compiler will complain there is an error, because Object cannot be converted to String.

public static int foo(String w, String v) {
    return w.length()-v.length();
}

public static void main(String[] args) {
    Object o1 = "abc", o2 = "bc";
    System.out.println(foo(o1, o2));// compiling error!
}
like image 474
maycui Avatar asked Jan 03 '23 14:01

maycui


1 Answers

You can use Object as arguments here because you used the raw type of Comparator, which is something that you generally should not do.

Here is where you did it:

Comparator c = SORT_BY_LENGTH;

See how there are not generic arguments to Comparator? That is a sign of using raw types. You can assign any instance of a parameterised type, like SORT_BY_LENGTH to a raw type. However, since the raw type Comparator has no generic parameters, its compare method takes two Objects instead of Strings. So you can theoretically pass anything into compare.

However, if the wrong type of object goes into the method, an exception will be thrown. Try putting two new Object() in there!

This is why you should not assign parameterised types to raw types. They are not type safe. You should do something like this instead:

Comparator<String> c = SORT_BY_LENGTH;

or use SORT_BY_LENGTH directly.

If you made the above change, the call to compare will not compile anymore, because it is expecting Strings. You should change the type of o1 and o2 to String.

like image 156
Sweeper Avatar answered Jan 05 '23 05:01

Sweeper