这是我的代码:
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 个字符串变量作为参数。但是,即使我输入 Object 类型的 2 个参数,它仍然有效。为什么?
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
s。所以理论上你可以把任何东西传递到compare
.
但是,如果方法中输入了错误类型的对象,则会引发异常。试着把两个new Object()
放进去!
这就是不应将参数化类型分配给原始类型的原因。它们不是类型安全的。你应该做这样的事情:
Comparator<String> c = SORT_BY_LENGTH;
或直接使用SORT_BY_LENGTH
。
如果进行了上述更改,则对compare
的调用将不再编译,因为它需要String
。应将o1
和o2
的类型更改为String
。