我有一个通用的java接口Id<T>
,其中包含一个方法T getId()
和一个实现MyClass
的类Id<Long>
。当我使用java反射检查MyClass
上声明的方法时,我看到两个方法:一个返回类型为Long
,另一个返回类型为Object
。第二种方法来自何处以及如何将其删除?
以下是来源:
package mypackage;
import java.lang.reflect.Method;
public class MainClass {
public static void main(String[] args) {
for (Method method : MyClass.class.getDeclaredMethods()) {
System.out.println(method);
}
// prints out two lines
// public java.lang.Long mypackage.MyClass.getId() <-- ok
// public java.lang.Object mypackage.MyClass.getId() <-- not ok
}
}
interface Id<T> {
T getId();
}
class MyClass implements Id<Long> {
@Override
public Long getId() {
return new Long(0);
};
}
答案 0 :(得分:3)
第二种方法是synthetic bridge
方法,您可以使用method.isSynthetic()
或method.isBridge()
进行检查。您无法删除它,但如果您不想在声明的方法列表中看到它,只需检查所有这些方法isBridge() == false
。
在编译期间,合成桥方法会自动添加到泛型类中。您可以阅读有关合成方法here的更多信息。
for (Method method : MyClass.class.getDeclaredMethods()) {
System.out.println("Method: " + method);
System.out.println("synthetic: " + method.isSynthetic());
System.out.println("bridge: " + method.isBridge());
}
// 1
//Method: public java.lang.Long Main$MyClass.getId()
//synthetic: false
//bridge: false
// 2
//Method: public java.lang.Object Main$MyClass.getId()
//synthetic: true
//bridge: true
答案 1 :(得分:2)
这是功能。
中提出了同样的问题JDK-8060179 Class.getDeclaredMethods() returning inconsistent results with generics并以'不是错误'结束。
答案 2 :(得分:1)
您可以通过javap -c MyClass
找到已编译的方法:
Compiled from "Test.java"
class MyClass implements Id<java.lang.Long> {
MyClass();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public java.lang.Long getId();
Code:
0: new #2 // class java/lang/Long
3: dup
4: lconst_0
5: invokespecial #3 // Method java/lang/Long."<init>":(J)V
8: areturn
public java.lang.Object getId();
Code:
0: aload_0
1: invokevirtual #4 // Method getId:()Ljava/lang/Long;
4: areturn
}
正如您所看到getId
有 2 方法,一个返回类型 Long
为implementation
而另一个<{1}} 返回类型是Object
类型(它正在调用Long getId
方法)。
返回类型 Object
方法用于在未指定泛型类型并桥接到Long getId
时进行处理方法。例如:
Id<Long> id = new Id<Long>() {
@Override
public Long getId() {
return null;
}
};
Long id1 = id.getId();
如上面的代码段,我们可以使用Id
类型实现Long
匿名类。但问题是我们也可以实现Id
匿名类,而不在变量中指定泛型类型:
Id id = new Id<Long>() {
@Override
public Long getId() {
return null;
}
};
Object id1 = id.getId();
所以现在编译器无法推断变量id
的泛型类型,当id.getId()
它返回类型Object
类型时变量,表示它调用此方法public java.lang.Object getId();
并桥接到public java.lang.Long getId();
方法。