Формат байт-кода 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)
должен выбрать тот, который является фактической реализацией.
возможно частный метод из родительского класса, соответствующий дочернему методу? – flakes
@flkes Нет, потому что 'getDeclaredMethods' только находит методы, объявленные в классе. Вы только когда-нибудь найдете метод, объявленный ребенку. – Radiodef