实现只包含一个接口的两种方法

Paw*_*wel 16 java generics interface type-erasure java-bridge-method

我创建了界面TwoMethods.源代码:

interface TwoMethods<T>
{
    public void method(T t);
}
Run Code Online (Sandbox Code Playgroud)

然后我创建了实现这个接口的类,在反汇编后我看到了2个方法.类:

class A implements TwoMethods<A>
{
    @Override
    public void method(A a) {}
}
Run Code Online (Sandbox Code Playgroud)

拆解后:

class A implements TwoMethods<A> {
   A();
   public void method(A); //first
   public void method(java.lang.Object); //second
}
Run Code Online (Sandbox Code Playgroud)

同样适用于Comparable界面.为什么当我创建参数化接口时,我有两种方法.总是,当我使用参数时?我还有另外的方法Object作为参数?

Eng*_*uad 18

method(java.lang.Object) 被称为桥接方法,它是由于编译时的类型擦除而生成的.

请参阅类型擦除和桥接方法的效果


Evg*_*eev 15

如果我们查看接口TwoMethods字节码,我们将看到实际的方法是

public abstract method(Ljava/lang/Object;)V
Run Code Online (Sandbox Code Playgroud)

即在约类型参数字节码级信息不存在,类型被擦除时,JVM根本不知道泛型,类型参数或者与取代Object或在情况下,如果T extends XX.所以从JVM的角度来看

class A implements TwoMethods<A> {
    public void method(A a) {
        ...
Run Code Online (Sandbox Code Playgroud)

method(A a)不会覆盖接口方法,因为在字节码中它method(Object obj)可以覆盖它.为了解决这个问题,编译器在A类中构建了一个隐式方法,即所谓的桥接方法

public void method(Object obj) {
     method((A)obj);
}
Run Code Online (Sandbox Code Playgroud)

仅在字节码中可见.现在为此代码

A a = new A();
TwoMethods<A> tm = a;
tm.method(a);
Run Code Online (Sandbox Code Playgroud)

编译器将替换tm.method(a)为对桥的调用

   INVOKEINTERFACE test/TwoMethods.method(Ljava/lang/Object;)V
Run Code Online (Sandbox Code Playgroud)

这会将呼叫重定向到 A.method(A a);