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
作为参数?
Evg*_*eev 15
如果我们查看接口TwoMethods字节码,我们将看到实际的方法是
public abstract method(Ljava/lang/Object;)V
Run Code Online (Sandbox Code Playgroud)
即在约类型参数字节码级信息不存在,类型被擦除时,JVM根本不知道泛型,类型参数或者与取代Object
或在情况下,如果T extends X
用X
.所以从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);