Несколько методов с одинаковыми типами параметров в классе

Я знаю, уже есть по крайней мере один вопрос по этой теме. Но я хочу спросить еще раз, потому что это то, что я обнаружил в 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) и выбрать тот, который является фактической реализации.