Класс 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);
Они явно показывают несколько методов с одной и той же сигнатурой вызова.
- как Java решает вызов функции?
- Почему существует множество функций?
EDIT: упростил вопрос, сохранив только соответствующий бит.
3 ответов:
Это связано с тем, как Java реализует ковариантные возвращаемые типы.
java.time.LocalTimeимеет методminusс сигнатуройLocalTime minus(TemporalAmount amountToSubtract)Но этот метод реализует метод интерфейса из
java.time.temporal.Temporalс сигнатуройTemporal minus(TemporalAmount amount)Это разрешено из-за ковариантного типа возврата, но из-за того, как работает метод lookup, поиск во время выполнения для метода, который возвращает a
Этот мостовой метод обычно невидим, но он появляется на выходеTemporal, не найдет метод, который возвращает aLocalTime. Таким образом, компилятор создает обычно запрещенный метод с тем же самым подпись, но возвращающая aTemporal. Этот метод вызывает версию, которая возвращает aLocalTime. Во время выполнения вызовы, которые хотят получить возвращаемый тип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