Статические методы в Java

#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:

Написанный вами код работает нормально, но, вероятно, не так, как вы предполагали. Статические методы не могут быть переопределены в традиционном смысле (или с поведением, которое вы могли бы ожидать). С точки зрения того, какая версия метода вызывается, это делается во время компиляции, что объясняет вывод, который вы видите.

Да, и вам, вероятно, следует вызывать методы только с использованием имени класса.