В Java статические методы не наследуются (или правильное слово переопределено ), но они могут быть скрыты .
Большое отличие здесь в том, что они не подвергаются полиморфизму, как метод объекта.
public class C1 {
static public void M1() {
System.out.println("C1.M1().");
}
static public void main(String ... Args) {
M1();
}
}
public class C2 extends C1 {
static public void M1() {
System.out.println("C2.M1().");
}
static public void main(String ... Args) {
M1();
C1.main(Args);
}
}
При запуске C2.main(null)
вы получите:
C2.M1().
C1.M1().
Как видите,
вызов M1()
в C1.main (...) относится к M1 из C1 и
вызов M1()
в C2.main (...) относится к M1 C2.
Вызов M1 (без префикса, см. Первую строку каждого main()
) не подвергается полиморфизму, так как M1 в C1 не переопределяется C2.
Но вызов из C2 относится к M1 из C2, так как M1 из C2 это hide тот, что в C1.
Подробнее здесь .
РЕДАКТИРОВАТЬ: Я только что перечитал ваш вопрос и просто посмотрел часть о "хорошей практике программирования".
Как я уже говорил, статический метод не наследуется, а скрывается, поэтому он так же хорош, как и другой метод.
С точки зрения кода, это совершенно разные методы.
Пусть скажут.
C1 has static method M1.
C2 extends C1 and has static method M1.
C3 extends C2.
При вызове M1 (без префикса) из C1 вы вызываете C1.M1 ().
Когда вы вызываете M1 (без префикса) из C2, вы вызываете C2.M1 (). // получить, но спрятаться
Когда вы вызываете M1 (без префикса) из C3, вы вызываете C3.M1 (). // выводим и не скрываем
Чтобы указать, какой метод, используйте имя класса, например C1.M1()
, C2.M1()
и C3.M1()
(это будет называться C2.M1()
).
Таким образом, эта реализация позволяет переопределять статический метод, но только как другой метод, а не как переопределенный (или замещающий) метод.
Следовательно, это обычно ничем не отличается от, скажем, именования их по-другому, например: C1_M()
и C2_M()
.
Итак, вы можете спросить, зачем вам эта функция? Я действительно не знаю. Возможно, позволяет более гибкое именование метода.
Но есть использование (которое может или не может быть намеренным), которое я использовал, это полиморфизм через отражение.
Поскольку вы можете вызывать и вызывать метод по имени, используя отражение, разрешение им иметь одно и то же имя приведет к полиморфизму при работе с помощью отражения.
Например (код выполнения может не работать):
String aClsName = "C1"; // "C2";
Class aCls = Class.forName(aClsName);
Method aMth = aCls.getMethod("M1"); // M1 of C1 or C2 depends on the class name.
aMth.invoke(null);
OR
Object aObj = new C1(); // new C2();
Class aCls = aObj.getClass();
Method aMth = aCls.getMethod("M1"); // M1 of C1 or C2 depends on the class of the object.
aMth.invoke(null);
Когда вы думаете об этом, я думаю, что Java тоже использует это (например, writeObject(...)
для сериализации), так что это может быть намерено.
Итак, в заключение следует сказать, что скрытие статического метода не является хорошей практикой программирования (Eclipse также рекомендует против него), но может быть полезно в двух случаях: (1) назвать метод точным, как предполагается, и (2) полиморф это с помощью отражения.
Надеюсь, это поможет.