Класс Java имеет 2 метода с одинаковой сигнатурой функции, но разными типами возвращаемых значений



AFAIK невозможно иметь метод с той же сигнатурой вызова. Однако:



$ javap -public java.time.LocalTime  | grep "minus" | grep "Temporal" | grep -v "long"
public java.time.LocalTime minus(java.time.temporal.TemporalAmount);
public java.time.temporal.Temporal minus(java.time.temporal.TemporalAmount);


Они явно показывают несколько методов с одной и той же сигнатурой вызова.




  1. как Java решает вызов функции?

  2. Почему существует множество функций?


EDIT: упростил вопрос, сохранив только соответствующий бит.

842   3  

3 ответов:

Это связано с тем, как Java реализует ковариантные возвращаемые типы. java.time.LocalTime имеет метод minus с сигнатурой

LocalTime minus(TemporalAmount amountToSubtract)

Но этот метод реализует метод интерфейса из java.time.temporal.Temporal с сигнатурой

Temporal minus(TemporalAmount amount)

Это разрешено из-за ковариантного типа возврата, но из-за того, как работает метод lookup, поиск во время выполнения для метода, который возвращает a Temporal, не найдет метод, который возвращает a LocalTime. Таким образом, компилятор создает обычно запрещенный метод с тем же самым подпись, но возвращающая a Temporal. Этот метод вызывает версию, которая возвращает a LocalTime. Во время выполнения вызовы, которые хотят получить возвращаемый тип Temporal, находят метод bridge, и все работает.

Этот мостовой метод обычно невидим, но он появляется на выходе javap, что приводит к вашей текущей путанице.

Источник: http://www.artima.com/weblogs/viewpost.jsp?thread=354443

Вот разборка javap -c для одного из методов моста из StringBuilder, показывающая как он вызывает метод с той же сигнатурой, но более специфическим типом возвращаемого значения:

  public java.lang.Appendable append(java.lang.CharSequence) throws java.io.IOException;
    Code:
       0: aload_0       
       1: aload_1       
       2: invokevirtual #6                  // Method append:(Ljava/lang/CharSequence;)Ljava/lang/StringBuilder;
       5: areturn       

Java запрещает два метода в одном классе или интерфейсе с одинаковым именем и подписью .

Однако два различных класса, интерфейса или перечисления могут иметь одну и ту же сигнатуру метода; например, это допустимо:
public java.time.LocalTime minus(long, java.time.temporal.TemporalUnit);
public java.time.temporal.Temporal minus(long, java.time.temporal.TemporalUnit);
Один метод minus принадлежит классу LocalTime, а другой-интерфейсу Temporal. С тех пор как LocalTime орудия труда Temporal, там должно быть соответствие подписи между этими двумя или контракт не выполняется, что приведет к к ошибке компиляции.

Temporal есть интерфейс, который реализован LocalTime, так что их методы имеют одинаковую сигнатуру если вы хотите проверить, попробуйте это

javap java.time.LocalTime

Comments

    Ничего не найдено.