count
полето е статично в Counter
класа, това означава, че можете да посочите променливата със следния израз: Counter.count
. 
private
полетата са налични само в класа, в който са декларирани. И protected
полетата са достъпни за всички класове в пакета, Howто и за всички техни подкласове извън пакета. Да предположим, че Counter
класът има статичен increment()
метод, чиято задача е да увеличаваcount
поле. За да извикате този метод, можете да използвате Counter.increment()
. Не е необходимо да създавате екземпляр на Counter
класа за достъп до статично поле or метод. Това е фундаменталната разлика между статичните (класови) променливи и методи и НЕстатичните (екземплярни) променливи и методи. Важна забележка. Не забравяйте, че статичните членове на класа принадлежат директно на класа, а не на който и да е екземпляр на класа. Тоест стойността на статичната count
променлива ще бъде една и съща за всички Counter
обекти. В тази статия ще разгледаме основните аспекти на използването на статичния модификатор в Java, Howто и някои функции, които ще ви помогнат да разберете ключови концепции за програмиране.
Какво трябва да знае всеки програмист за статичния модификатор в Java.
В този раздел разглеждаме основните аспекти на използването на статични методи, полета и класове. Да започнем с променливите.-
НЕ МОЖЕТЕ да осъществявате достъп до нестатични членове на клас в рамките на статичен контекст, като например статичен метод or блок. Компorрането на codeа по-долу ще доведе до грешка:
public class Counter { private int count; public static void main(String args []) { System.out.println(count); // Compile time error } }
Това е една от най-честите грешки, допускани от Java програмистите, особено от начинаещите. Тъй като
main
методът е статичен, аcount
променливата не е, използването наprintln
метода вътре вmain
метода ще доведе до „грешка при компorране“. -
За разлика от локалните променливи, статичните полета и методи НЕ са
thread safe
в Java. На практика това е една от най-честите причини за проблеми със сигурността при многопоточното програмиране. Като се има предвид, че всяко копие на клас препраща към едно и също копие на статична променлива, такава променлива трябва да бъде защитена or „заключена“ от класа. Следователно, когато използвате статични променливи, уверете се, че те са правилни,synchronized
за да избегнете проблеми катоrace conditions
. -
Статичните методи имат практическо предимство, тъй като не е необходимо да създавате нов обект всеки път, когато искате да ги извикате. Статичен метод може да бъде извикан с помощта на името на класа, който го декларира. Ето защо тези методи са идеални за
factory
методи иutility
методи. Класътjava.lang.Math
е чудесен пример: почти всичките му методи са статични. Полезните класове на Java са маркираниfinal
по същата причина. -
Друг важен момент е, че не можете да замените (
@Override
) статични методи. Ако декларирате такъв метод вsubclass
, т.е. метод със същото име и подпис, вие просто "скривате" метода наsuperclass
instead of да го замествате. Това явление е известно катоmethod hiding
. Това означава, че ако статичен метод е деклариран Howто в родителски, така и в дъщерен клас, извиканият метод винаги ще се основава на типа на променливата по време на компorране. За разлика от отмяната на метода, такива методи няма да бъдат изпълнени, когато програмата се изпълнява. Да разгледаме един пример:class Vehicle { public static void kmToMiles(int km) { System.out.println("Inside the parent class / static method"); } } class Car extends Vehicle { public static void kmToMiles(int km) { System.out.println("Inside the child class / static method"); } } public class Demo { public static void main(String args []) { Vehicle v = new Car(); v.kmToMiles(10); } }
Конзолен изход:
Вътре в родителския клас/статичен метод
Кодът ясно показва, че въпреки факта, че обектът е
Car
, статичният метод вVehicle
класа се извиква, тъй като методът е извикан по време на компorране. И имайте предвид, че няма грешки при компorрането! -
Нещо повече, освен класове от най-високо ниво, можете да декларирате класове статични. Такива класове са известни като
nested static classes
. Те са полезни за осигуряване на по-добра кохезия. Ярък пример за вложен статичен клас еHashMap.Entry
, който е структура от данни вътреHashMap
. Струва си да се отбележи, че подобно на вътрешните класове, статичните вложени класове се декларират в отделен .class файл. Така, ако декларирате пет вложени класа във вашия основен клас, ще имате 6 file с разширение .class. Друг пример е нашата собствена декларацияComparator
, като например сравнител за възраст (AgeComparator
) вEmployee
класа. -
Статичният модификатор може също да бъде указан в статичен блок, по-известен като "блок за статична инициализация", който се изпълнява, когато класът се зареди. Ако не декларирате такъв блок, Java събира всички статични полета в един списък и ги инициализира, когато класът се зареди. Статичният блок НЕ МОЖЕ да хвърля проверени изключения, но може да хвърля непроверени. В този случай
ExceptionInInitializerError
ще възникне. На практика всяко изключение, което възниква по време на инициализация на статични полета, ще бъде обвито в тази грешка от Java. Това е и най-честата причина заNoClassDefFoundError
, защото класът няма да бъде в паметта, когато се препраща към него. -
Полезно е да знаете, че статичните методи се свързват по време на компorране, за разлика от свързването на виртуални or нестатични методи, които се свързват по време на изпълнение, когато се извикват на реален обект. Съответно, статичните методи не могат да бъдат отменени в Java, тъй като полиморфизмът не се прилага към тях по време на изпълнение. Това е важно ограничение, което трябва да имате предвид, когато декларирате статичен метод. Това има смисъл само когато няма възможност or необходимост от замяна на метода в подклас. Фабричните методи и помощните методи са добри примери за правилно използване на статичния модификатор. Джошуа Блох посочва няколко предимства, които статичните фабрични методи имат пред конструкторите в книгата си Effective Java, която е задължително четиво за всеки Java програмист.
-
Инициализирането е важен аспект на статичен блок. Статичните полета or променливи се инициализират, след като класът се зареди в паметта. Редът на инициализация е отгоре надолу, в същия ред, в който са декларирани в изходния файл на Java класа. Тъй като статичните полета се инициализират по безопасен за нишката начин, този процес се използва и за прилагане на
Singleton
шаблона. Ако не използватеEnum
катоSingleton
по няHowва причина, тогава имате добра алтернатива. Но в този случай трябва да имате предвид, че това не е "мързелива" инициализация. Това означава, че статичното поле ще бъде инициализирано дори ПРЕДИ някой да го "поиска". Ако даден обект изисква много ресурси or се използва рядко, тогава инициализирането му в статичен блок няма да работи във ваша полза. -
По време на сериализация статичните полета, подобно
transient
на променливите, не се сериализират. Наистина, ако запишете няHowви данни в статично поле, то ще съдържа първоначалната си (по подразбиране) стойност след десериализация. Например, ако статично поле еint
, стойността му ще бъде нула след десериализация. Ако неговият тип еfloat
, стойността ще бъде 0.0. Ако полето еObject
, стойността ще бъдеnull
. Честно казано, това е един от най-често задаваните въпроси относно сериализацията в интервюта за позиции в Java. Не съхранявайте основни обектни данни в статично поле! -
И накрая, нека поговорим за статичен импорт. Този модификатор има много общо със стандартния
import
оператор, но е различен по това, че ви позволява да импортирате един or всички статични членове на класа. След като статичните методи бъдат импортирани, те могат да бъдат достъпни, сякаш са декларирани в същия клас. По същия начин, като импортираме статични полета, можем да имаме достъп до тях, без да посочваме името на класа. Тази функция се появи в Java 1.5 и подобрява четимостта на codeа, когато се използва правилно. Тази конструкция се среща най-често в JUnit тестове, тъй като почти всички разработчици на тестове използват статичен импорт за assert методи, напримерassertEquals()
и техните претоварени варианти. -
Това е всичко за сега. Всеки Java програмист трябва да знае всички аспекти на статичния модификатор, споменат по-горе. Тази статия прегледа основна информация за статични променливи, полета, методи, блокове за инициализация и импортиране. Той също така засегна някои важни свойства, които е важно да знаете, за да пишете и разбирате Java програми. Надявам се, че всеки разработчик ще усъвършенства умелото си използване на статични членове, защото това е много важно за сериозното разработване на софтуер."
GO TO FULL VERSION