Вы можете подумать о том, чтобы сделать статический метод final, учитывая следующее:
Имея следующие классы:
class A {
static void ts() {
System.out.print("A");
}
}
class B extends A {
static void ts() {
System.out.print("B");
}
}
Теперь "правильный" способ вызова этих методов был бы
A.ts();
B.ts();
что приведет к тому, AB
но вы также можете вызвать методы для экземпляров:
A a = new A();
a.ts();
B b = new B();
b.ts();
что также приведет AB
к.
Теперь рассмотрим следующее:
A a = new B();
a.ts();
что бы напечатать A
. Это может вас удивить, поскольку на самом деле у вас есть объект класса B
. Но поскольку вы вызываете его из ссылки типа A
, он вызовет A.ts()
. Вы можете печатать B
с помощью следующего кода:
A a = new B();
((B)a).ts();
В обоих случаях объект, который у вас есть, действительно принадлежит классу B
. Но в зависимости от указателя, указывающего на объект, вы будете вызывать метод from A
или from B
.
Теперь предположим, что вы разработчик класса A
и хотите разрешить подклассы. Но вам действительно нужен метод ts()
, когда бы он ни вызывался, даже из подкласса, который делал бы то, что вы хотите, а не был бы скрыт версией подкласса. Тогда вы можете сделать это final
и предотвратить его скрытие в подклассе. И вы можете быть уверены, что следующий код вызовет метод из вашего класса A
:
B b = new B();
b.ts();
Хорошо, по общему признанию, это каким-то образом сконструировано, но в некоторых случаях это может иметь смысл.
Вы должны вызывать статические методы не в экземплярах, а непосредственно в классах - тогда у вас не будет этой проблемы. Также IntelliJ IDEA, например, покажет вам предупреждение, если вы вызовете статический метод в экземпляре, а также если вы сделаете статический метод final.