如何使用java中的桥接技术实现协变方法覆盖

Pra*_*eek 5 java generics overriding covariant

在阅读Covariant Overriding时,我发现了一个非常奇怪的事实,

使用桥接技术实现协变方法覆盖.它还说这个功能是在java5及以上版本中实现的.(我认为这是因为java5引入了泛型)

怎么回事.请帮我举个例子.

Roh*_*ain 8

考虑一个例子:

public interface Shape<T extends Shape<T>> {
    T getType();
    void setType(T type);
}

public class Circle implements Shape<Circle> {
    Circle getType() { }
    void setType(Circle circle) {  }
}
Run Code Online (Sandbox Code Playgroud)

它现在看起来不错.但是,在类型擦除之后,接口松开它的泛型类型,并且类型T被替换为上限.所以接口和类看起来像:

public interface Shape {
    Shape getType();
    void setType(Shape type);
}

public class Circle implements Shape {
    Circle getType() { }
    void setType(Circle circle) {  }
}
Run Code Online (Sandbox Code Playgroud)

现在,这是问题所在.Circle擦除后的方法实际上并不是一个被覆盖的版本Shape.请注意,现在看起来的方法对它所采用的参数以及它返回的值应用了更大的限制.这是因为擦除会改变界面中方法的签名.

为了解决这个问题,编译器为那些添加了桥接方法,它将调用委托给类中的那些实际方法.

所以,这个类真的转换为:

public class Circle implements Shape {
    Circle getType() { }
    void setType(Circle circle) {  }

    // Bridge method added by compiler.
    Shape getType() { return getType(); }  // delegate to actual method
    void setType(Shape shape) { setType((Circle)shape); }  // delegate to actual method
}
Run Code Online (Sandbox Code Playgroud)

因此,bridge方法现在是接口中方法的重写版本,并且它们将调用委托给执行任务的实际方法.

注意,在这种情况下,桥接方法中使用的类型是接口的类型参数的擦除Shape.


参考文献:

  • @sp00m:如果您尝试将其传递给 Java 编译器,则会出现错误,因为方法不能仅因返回类型而异。但在 JVM 字节码级别,该限制不存在。 (3认同)