Чтобы объяснить, что такое семантика, нам нужно взглянуть на то, как дифференцируются Java методы.
В Java метод идентифицируется его сигнатурой. JLS §8.4.2 указывает, что
Два метода имеют одинаковую подпись, если они имеют одинаковые имена и типы аргументов.
Важно отметить является то, что тип возвращаемого значения метода не часть сигнатуры метода. Таким образом, если бы вы написали:
public class Foo {
void bar(String baz) {
}
String bar(String baz) {
}
}
Оба метода имели бы одинаковую подпись. В Java это приведет к ошибке компиляции, поскольку в одном классе нельзя использовать два метода с одинаковой сигнатурой.
Поведение изменится, если мы примем наследование в изображение:
public class Foo {
void bar(String baz);
}
public class Zoo extends Foo {
@Override
void bar(String baz);
}
В этом случае класс Zoo
переопределяет метод bar(...)
класса Foo
. Обратите внимание, что аннотация не отвечает за поведение и просто проверяет время компиляции, чтобы убедиться, что есть метод void bar(String baz)
хотя бы в одном родительском классе.
В представленном коде есть два метода с одинаковым именем , но разные подписи. Это называется Перегрузка в Java. Таким образом, метод трактуется как не «равный». Вы можете переименовать один из этих методов, и они не будут более или менее «равными».
Чтобы сделать вещи еще более странными, если методы перегружены, подпись для вызываемого метода создается во время компиляции. Это означает, что могут рассматриваться только параметры типа stati c. Давайте посмотрим на следующий код и выясним, каков будет результат:
public class Test {
public static void main(final String... args) {
final String s = "foo";
final Object o = s;
print(s);
print(o);
}
private static void print(final String s) {
System.out.println("Called with String parameter");
}
private static void print(final Object o) {
System.out.println("Called with Object parameter");
}
}
Ideon demo
Теперь, что такое состояние c тип s
? Это тип слева, где было объявлено s
, поэтому вызывается print(final String s)
и печатается "Called with String parameter"
. Что такое тип c stati o
? Опять же, это тип слева, где o
был объявлен, и, таким образом, print(final Object o)
вызывается и "Called with Object parameter"
распечатывается. Можно утверждать, что в этом тривиальном примере компилятор может выяснить, что тип o
может быть только String
, но основание этого поведения на способности компилятора распознавать типы во время компиляции делает его еще более запутанным .