带有Object.Class参数的Class::getMethod是如何工作的


public static void main(String[] args) throws NoSuchMethodException, SecurityException {
Method method = String.class.getMethod("compareTo", Object.class);
System.out.println(method);
}

打印public int java.lang.String.compareTo(java.lang.Object)

public static void main(String[] args) throws NoSuchMethodException, SecurityException {
"Foo".compareTo(new Object());
}

不编译,因为The method compareTo(String) in the type String is not applicable for the arguments (Object)

为什么?

String实现了Comparable<String>,它定义了方法compareTo(T o)

由于类型擦除,该方法在运行时实际上是compareTo(Object o)

不管怎样,String将该方法实现为compareTo(String o)

由于它具有不同的签名,Java编译器生成一个";合成的""桥";使其工作的方法,这意味着你最终会得到:

public interface Comparable {
public int compareTo(Object o);
}
public class String implements Comparable {
public int compareTo(String o) {
...
}
public synthetic bridge int compareTo(Object o) {
return compareTo((String) o);
}
}

syntheticbridge当然不是可以放在Java源文件中的实际关键字,但这些修饰符在运行时存在于反射数据中。

合成方法是由编译器出于内部原因生成的,因此它们被认为是"隐藏";,这意味着您无法在Java源文件中看到它们,这就是compareTo(new Object())不会编译的原因。

然而,您可以通过反射看到该方法,但正如您从这里显示的实现中看到的那样,如果您实际上通过反射调用了compareTo(new Object()),则会得到ClassCastException

这正是泛型要解决的问题。在编译时,编译器可以使用泛型来告诉您将String与Object进行比较是无效的。

然而,在运行时,泛型会被擦除。因此,您可以根据Object方法参数将String与Object进行比较。

最新更新