2016-04-18 6 views
8

Я знаю, что есть уже не менее one question on this topic. Но я хочу спросить его снова, потому что это то, что я обнаружил в javadoc of Class#getDeclaredMethod(...):Более одного метода с теми же параметрами в классе

Если более чем один метод с теми же типами параметров объявлен в классе, и один из этих способов имеет тип возврата, больше , чем любой другой, этот метод возвращается; иначе один из методов выбирается произвольно.

Так что разработчики отражения в java считают этот случай вероятным, возможно ли, возможно, сделать такое объявление? Или это может быть просто устарело?

+0

возможно частный метод из родительского класса, соответствующий дочернему методу? – flakes

+2

@flkes Нет, потому что 'getDeclaredMethods' только находит методы, объявленные в классе. Вы только когда-нибудь найдете метод, объявленный ребенку. – Radiodef

ответ

9

Формат байт-кода JVM допускает объявление нескольких методов с тем же именем и теми же параметрами, если тип возвращаемого значения отличается, хотя язык Java этого не допускает. Это означает, что а) другие языки JVM могут использовать это, и б) его можно использовать для специальных функций языка «компилятор-магия».

Как правило, компилятор испускает несколько методов с тем же именем и теми же параметрами при работе с дженериками. Поиск метода JVM зависит от целой сигнатуры, а не только от типов параметров. Таким образом, компилятор должен испускать так называемые методы bridge, которые переопределяют или теневые другие методы подписи. Рассмотрим следующий пример:

interface Foo<T> 
{ 
    T foo(); // desc:()Ljava/lang/Object; 

    void bar(T value); // desc: (Ljava/lang/Object;)V 

    Object baz(); // desc:()Ljava/lang/Object; 
} 

class StringFoo implements Foo<String> 
{ 
    @Override 
    public String foo() { ... } // desc:()Ljava/lang/String; // ! 

    @Override 
    public void bar(String value) { ... } // desc: (Ljava/lang/String;)V // ! 

    @Override 
    public String baz() { ... } // desc:()Ljava/lang/String; // ! 
} 

StringFoo класс нуждается в трех дополнительных методов моста, чтобы фактически переопределить методы интерфейса в терминах, имеющих тот же desc:

class StringFoo implements Foo<String> 
{ 
    public String foo() { ... } 

    public /* synthetic bridge */ Object foo() // desc:()Ljava/lang/Object; 
    { 
     return /* String */ foo(); // statically linked to String foo() 
    } 

    public void bar(String value) { ... } 

    public /* synthetic bridge */ void bar(Object value) // desc: (Ljava/lang/Object;) 
    { 
     return bar((String) value); 
    } 

    public String baz() { ... } 

    public /* synthetic bridge */ Object baz() // desc:()Ljava/lang/Object; 
    { 
     return /* String */ baz(); // statically linked to String baz() 
    } 
} 

псевдо-модификаторы synthetic bridge два доступа к виртуальной машины Java флагов, которые используются компилятором только для обозначения автоматических методов в байт-кодексе

Class#getDeclaredMethods meth od возвращает все объявленные методы - в том числе синтетические мостовые методы. Таким образом, #getDeclaredMethod(String) должен выбрать тот, который является фактической реализацией.

+0

Не могли бы вы объяснить или предоставить ссылку на то, что такое «синтетический мост»? – flakes

+0

@flkes отредактирован. Эти псевдомодификаторы не особенно важны для пользователя, компилятор просто использует их для обозначения специальных методов. – Clashsoft

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