Несколько методов с одинаковыми типами параметров в классе
Я знаю, уже есть по крайней мере один вопрос по этой теме. Но я хочу спросить еще раз, потому что это то, что я обнаружил в javadoc Class#getDeclaredMethod(...)
:
если в a объявлено несколько методов с одинаковыми типами параметров class, и один из этих методов имеет возвращаемый тип, который больше конкретный, чем любой из других, этот метод возвращается; в противном случае один из методов выбран произвольно.
таким образом, разработчики отражения в java считают этот случай вероятным, возможно ли все-таки сделать такое объявление? Или, может быть, это просто устарело?
1 ответов
формат байт-кода JVM разрешает объявление нескольких методов с тем же именем и теми же типами параметров, пока тип возврата отличается, хотя Java язык не допускает этого. Это означает, что a) другие языки JVM могут использовать это и b) его можно использовать для специальных функций языка "компилятор-магия".
чаще всего компилятор выдает несколько методов с одинаковым именем и одинаковыми типами параметров при работе с дженериками. Поиск метода 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; // !
}
The 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
два флага доступа JVM, которые только используется компилятором для пометки автоматически генерируемых методов в байт-коде
The Class#getDeclaredMethods
возвращает все объявленные методы-включая методы синтетического моста. Таким образом, #getDeclaredMethod(String)
и выбрать тот, который является фактической реализации.