英文:
How does Class::getMethod with an Object.class parameter work?
问题
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());
}
无法编译,因为 `String` 类中的方法 `compareTo(String)` 不适用于参数 (Object)`。
为什么?
英文:
public static void main(String[] args) throws NoSuchMethodException, SecurityException {
Method method = String.class.getMethod("compareTo", Object.class);
System.out.println(method);
}
Prints public int java.lang.String.compareTo(java.lang.Object)
.
public static void main(String[] args) throws NoSuchMethodException, SecurityException {
"Foo".compareTo(new Object());
}
Doesn't compile, because The method compareTo(String) in the type String is not applicable for the arguments (Object)
.
Why?
答案1
得分: 2
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);
}
}
“synthetic” 和 “bridge” 当然不是你可以放在 Java 源文件中的实际关键字,但这些修饰符在运行时的反射数据中存在。
“合成”方法是由编译器为内部原因生成的,因此它们被视为“隐藏”,这意味着你在 Java 源文件中看不到它们,这就是为什么 compareTo(new Object())
无法编译。
但是,你可以通过反射看到该方法,但正如在这里显示的实现所示,如果你通过反射实际调用 compareTo(new Object())
,你会得到一个 ClassCastException
。
英文:
String
implements Comparable<String>
, which defines method compareTo(T o)
.
Because of type-erasure, that method is actually compareTo(Object o)
at runtime.
Regardless of that, String
implements that method as compareTo(String o)
.
Since that has a different signature, the Java compiler generates a "synthetic" "bridge" method to make it work, which means you end up with:
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);
}
}
synthetic
and bridge
are of course not actual keywords you can put in a Java source file, but those modifiers are present in the reflection data at runtime.
Synthetic methods are generated by the compiler for internal reasons, so they are considered "hidden", which means you cannot see them in a Java source file, and that is why compareTo(new Object())
will not compile.
You can however see the method through reflection, but as you can see from the implementation shown here, if you actually called compareTo(new Object())
through reflection, you'd get a ClassCastException
.
答案2
得分: 0
这正是泛型旨在解决的问题。在编译时,编译器可以使用泛型来告诉您,将 String 与 Object 进行比较是行不通的。
然而,在运行时,泛型会被擦除。因此,您可以根据 Object 方法参数将 String 与 Object 进行比较。
英文:
This is exactly the issue that generics work to fix. At compile time, the compiler can use generics to tell you that comparing a String to an Object will not work.
At runtime however, generics are erased. So you can compare a String to an Object, as per the Object method parameters.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论