Вы можете подумать о том, чтобы сделать статический метод 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
. Но в зависимости от указателя, указывающего на объект, вы будете вызывать метод из A
или из B
.
Теперь предположим, что вы являетесь разработчиком класса A
и хотите разрешить создание подклассов. Но вы действительно хотите, чтобы метод ts()
всякий раз вызывался, даже из подкласса, то есть делал то, что вы хотите, и не был скрыт версией подкласса. Затем вы можете сделать его final
и предотвратить его скрытие в подклассе. И вы можете быть уверены, что следующий код вызовет метод из вашего класса A
:
B b = new B();
b.ts();
Хорошо, допустим, это как-то устроено, но в некоторых случаях это может иметь смысл.
Вы не должны вызывать статические методы для экземпляров, а непосредственно для классов - тогда у вас не будет этой проблемы. Также IntelliJ IDEA, например, покажет вам предупреждение, если вы вызовете статический метод для экземпляра, а также если вы сделаете статический метод окончательным.
person
Mathias Bader
schedule
12.09.2017