#java
#java
Вопрос:
Я новичок в программировании на Java. Кто-нибудь, пожалуйста, может объяснить мне, почему программа выдает — «fa la», даже если статический метод переопределен. Я читал, что статические методы не могут быть переопределены в Java? Пожалуйста, поправьте меня, если я ошибаюсь.
public class Tenor extends Singer {
public static String sing() {
return "fa";
}
public static void main(String[] args) {
Tenor t = new Tenor();
Singer s = new Tenor();
System.out.println(t.sing() " " s.sing());
}
}
class Singer {
public static String sing() {
return "la";
}
}
Ответ №1:
Вы не можете переопределить статические методы в Java. Это просто вызов статических методов непосредственно в каждом классе. Кстати: Как отмечали другие, вызывать статические методы в экземплярах считается плохой практикой. Для наглядности вам следует выполнить следующее:
System.out.println(Tenor.sing() " " Singer.sing());
что эквивалентно коду, который вы написали в своем вопросе.
Комментарии:
1. Если я правильно помню, вызов статического метода в экземпляре должен выдавать предупреждение компилятора…
Ответ №2:
Доступ к статическим методам следует осуществлять с именем класса, а не ссылкой на объект. Правильным эквивалентом того, что вы написали, было бы:
System.out.println(Tenor.sing() " " Singer.sing())
Java угадывает, какой метод вы хотели вызвать, основываясь на типе переменной объекта.
РЕДАКТИРОВАТЬ: как указал Стивен, это не угадывание. Вывод, вероятно, был бы более точным словом. Я просто пытался подчеркнуть, что вызов статических функций по ссылкам на объекты может привести к поведению, которого вы не ожидаете. На самом деле, я только что попробовал несколько вещей и обнаружил, что мое предыдущее утверждение было неверным: Java решает, какой метод вызывать, на основе типа переменной. Теперь, когда я больше думаю об этом, это очевидно, но я вижу, как это могло бы привести к путанице, если бы вы сделали что-то вроде:
Singer s = new Tenor();
System.out.println(s.sing());
Комментарии:
1. Java ни о чем не догадывается . Значение вызова статического метода четко указано в JLS, наряду с тем фактом, что статические методы не переопределяются.
Ответ №3:
t
имеет тип Tenor
и s
имеет тип Singer
.
Когда вы вызываете статический метод в экземпляре (что является плохой практикой), вы вызываете статический метод в классе объявленного типа.
т. е. t.sing()
эквивалентно Tenor.sing()
Комментарии:
1. Я просто подумал, что стоит упомянуть, что я только что попробовал некоторый код и, на удивление,
Singer s = null; s.sing()
работает просто отлично. Можете ли вы представить, что видите это в коде и это работает необъяснимым образом?
Ответ №4:
Статические методы не переопределяются. Они принадлежат классу, в котором они определены. Вызов статического метода в экземпляре этого метода работает так же, как и вызов его в классе, но делает вещи менее понятными и приводит к тому, что люди думают, что они переопределены, как методы экземпляра.
Ответ №5:
Статические методы не могут быть переопределены.
следующий ресурс поможет вам лучше понять, что происходит, когда вы пытаетесь переопределить статический метод:
http://www.javabeat.net/qna/49-can-we-override-static-methods-what-is-metho/
С уважением, Кирилл
Ответ №6:
Написанный вами код работает нормально, но, вероятно, не так, как вы предполагали. Статические методы не могут быть переопределены в традиционном смысле (или с поведением, которое вы могли бы ожидать). С точки зрения того, какая версия метода вызывается, это делается во время компиляции, что объясняет вывод, который вы видите.
Да, и вам, вероятно, следует вызывать методы только с использованием имени класса.