我创建了界面TwoMethods
。源代码:
interface TwoMethods<T>
{
public void method(T t);
}
然后我创建了实现此接口的类,在反汇编后我看到了2个方法。 类:
class A implements TwoMethods<A>
{
@Override
public void method(A a) {}
}
拆解后:
class A implements TwoMethods<A> {
A();
public void method(A); //first
public void method(java.lang.Object); //second
}
同样适用于Comparable
接口。为什么当我创建参数化接口时,我有两种方法。总是,当我使用参数时?我还有Object
作为参数的方法吗?
答案 0 :(得分:18)
method(java.lang.Object)
被称为桥接方法,它是在编译时因类型擦除而生成的。
答案 1 :(得分:15)
如果我们查看接口TwoMethods字节码,我们将看到实际的方法是
public abstract method(Ljava/lang/Object;)V
在类型参数的字节码级别信息不存在,类型被删除,JVM根本不知道泛型,类型参数用Object
替换,或者如果T extends X
替换{ {1}}。所以从JVM的角度来看
X
class A implements TwoMethods<A> {
public void method(A a) {
...
不会覆盖接口方法,因为在method(A a)
中的字节码可以覆盖它。为了解决这个问题,编译器在A类中构建了一个隐式方法,即所谓的桥接方法
method(Object obj)
仅在字节码中可见。现在为此代码
public void method(Object obj) {
method((A)obj);
}
编译器将通过调用桥接器替换A a = new A();
TwoMethods<A> tm = a;
tm.method(a);
tm.method(a)
这会将调用重定向到 INVOKEINTERFACE test/TwoMethods.method(Ljava/lang/Object;)V