为什么 Java 允许 compare(String, String) Comparator 方法接受 Object 类型的参数?

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

所以这是我的代码:

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
    }
}

所以让我感到困惑的是 compare() 方法的签名将 2 个字符串变量作为参数。但是,即使我输入 2 个 Object 类型的参数,它仍然有效。这是为什么?

PS: 如果我像下面这样定义一些普通的方法,那么编译器会报错,因为Object不能转换成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!
}

你可以在这里使用Object作为参数,因为你使用了Comparator原始类型,这是你通常不应该做的事情。

这是你做的地方:

Comparator c = SORT_BY_LENGTH;

看看 Comparator 怎么没有通用参数?这是使用原始类型的标志。您可以将参数化类型的任何实例(例如 SORT_BY_LENGTH)分配给原始类型。但是,由于原始类型 Comparator 没有泛型参数,因此它的 compare 方法需要两个 Object 而不是 String。所以理论上你可以将任何东西传递给 compare.

但是,如果错误类型的对象进入该方法,将抛出异常。试试把两个 new Object() 放在那里!

这就是为什么您不应将参数化类型分配给原始类型。它们不是类型安全的。你应该做这样的事情:

Comparator<String> c = SORT_BY_LENGTH;

或直接使用SORT_BY_LENGTH

如果您进行了上述更改,对 compare 的调用将不再编译,因为它需要 Strings。您应该将 o1o2 的类型更改为 String.