Можливо, ви можете подумати про те, щоб статичний метод остаточним, враховуючи наступне:
Проводячи наступні класи:
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, наприклад, покаже вам попередження, якщо ви викликаєте статичний метод в екземплярі, а також якщо статичний метод буде остаточним.