2013-12-25 1 views
16

Я создал интерфейс 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 интерфейса. Почему, когда я создаю параметризованный интерфейс, у меня есть 2 метода. Всегда, когда я использую параметр? У меня есть метод с Object как аргумент?

ответ

15

Если мы посмотрим на интерфейс TwoMethods байткоде мы увидим, что фактический метод

public abstract method(Ljava/lang/Object;)V 

что на информации об уровне байткода о параметре типа не существует, тип стирается, JVM просто не знают о дженериках, параметры типа заменяются либо Object, либо в случае, если T extends X с X. Таким образом, с точки зрения виртуальной машины Java

class A implements TwoMethods<A> { 
    public void method(A a) { 
     ... 

method(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 

и это будет перенаправлять вызов A.method(A a);

Смежные вопросы