Ръководство за статичната ключова дума в Java

1. Въведение

В тази статия ще разгледаме подробно статичната ключова дума на езика Java. Ще открием как можем да приложим статична ключова дума към променливи, методи, блокове, вложени класове и каква е разликата.

2. Анатомията на статичната ключова дума

В езика за програмиране Java ключовата дума static показва, че конкретният член принадлежи на самия тип, а не на екземпляр от този тип .

Това означава, че се създава само един екземпляр на този статичен член, който се споделя във всички екземпляри на класа.

Ключовата дума може да се приложи към променливи, методи, блокове и вложен клас.

3. Статичните полета (или променливи на класа)

В Java, ако дадено поле е обявено за статично , тогава се създава точно едно копие на това поле и се споделя между всички екземпляри от този клас . Няма значение колко пъти инициализираме клас; винаги ще има само едно копие на статично поле, принадлежащо към него. Стойността на това статично поле ще бъде споделена за всички обекти от всеки един от всеки от различен клас.

От гледна точка на паметта статичните променливи влизат в определен пул в JVM паметта, наречен Metaspace (преди Java 8, този пул се е наричал Permanent Generation или PermGen, който е напълно премахнат и заменен с Metaspace).

3.1. Пример за статично поле

Да предположим, че имаме клас Car с няколко атрибута (променливи на екземпляра) . Когато всеки обект се инициализира от този проект на Car , всеки нов обект ще има своето отделно копие на тези променливи на екземпляра.

Да предположим обаче, че търсим променлива, която съдържа броя на обектите на Car, които са инициализирани и е споделена във всички екземпляри, така че те да имат достъп до нея и да я увеличават при инициализацията си.

Ето къде влизат статичните променливи:

public class Car { private String name; private String engine; public static int numberOfCars; public Car(String name, String engine) { this.name = name; this.engine = engine; numberOfCars++; } // getters and setters }

Сега за всеки обект от този клас, който се инициализира, същото копие на променливата numberOfCars се увеличава. Така че в този случай ще бъдат верни следните твърдения:

@Test public void whenNumberOfCarObjectsInitialized_thenStaticCounterIncreases() { new Car("Jaguar", "V8"); new Car("Bugatti", "W16"); assertEquals(2, Car.numberOfCars); }

3.2. Принудителни причини за използване на статични полета

  • Когато стойността на променливата е независима от обектите
  • Когато стойността трябва да бъде споделена между всички обекти

3.3. Основни моменти, които трябва да запомните

  • Тъй като статичните променливи принадлежат на клас, те могат да бъдат достъпни директно с помощта на името на класа и не се нуждаят от никаква препратка към обект
  • статичните променливи могат да бъдат декларирани само на ниво клас
  • статичните полета могат да бъдат достъпни без инициализация на обект
  • Въпреки че можем да осъществим достъп до статични полета, като използваме препратка към обект (като ford.numberOfCars ++ ), трябва да се въздържаме от използването му, тъй като в този случай става трудно да разберем дали това е променлива на инстанция или променлива на клас; вместо това винаги трябва да се позоваваме на статични променливи, като използваме име на клас (например в този случай Car.numberOfCars ++ )

4. Статичните методи (или методи на клас)

Подобно на статичните полета, статичните методи също принадлежат на клас вместо обекта и затова могат да бъдат извикани, без да се създава обектът на класа, в който се намират. Те са предназначени да се използват, без да се създават обекти от класа.

4.1. Пример за статичен метод

статичните методи обикновено се използват за извършване на операция, която не зависи от създаването на екземпляр.

Ако има код, който трябва да бъде споделен във всички екземпляри от този клас, тогава напишете този код в статичен метод:

public static void setNumberOfCars(int numberOfCars) { Car.numberOfCars = numberOfCars; }

статичните методи също се използват широко за създаване на помощни или помощни класове, така че да могат да бъдат получени, без да се създава нов обект от тези класове.

Просто погледнете колекциите или помощните класове по математика от JDK, StringUtils от Apache или CollectionUtils от Spring framework и забележете, че всички методи са статични .

4.2. Принудителни причини за използване на статични методи

  • За достъп / манипулиране на статични променливи и други статични методи, които не зависят от обекти
  • статичните методи се използват широко в помощните класове и помощните класове

4.3. Основни моменти, които трябва да запомните

  • статичните методи в Java се решават по време на компилация. Тъй като заместването на метода е част от полиморфизма по време на изпълнение, така статичните методи не могат да бъдат заменени
  • абстрактните методи не могат да бъдат статични
  • статичните методи не могат да използват тази или супер ключови думи
  • Следните комбинации от екземпляра, методите на класа и променливите са валидни:
    1. Методите на екземпляра могат директно да имат достъп както до методите на инстанцията, така и до променливите на инстанцията
    2. Методите на екземпляра могат също да осъществяват директен достъп до статични променливи и статични методи
    3. статичните методи имат достъп до всички статични променливи и други статични методи
    4. статичните методи не могат да имат директен достъп до променливи на инстанции и методи ; те се нуждаят от някаква справка за обект, за да го направят

5. Статичен блок

За инициализиране на статични променливи се използва статичен блок . Въпреки че статичните променливи могат да бъдат инициализирани директно по време на декларирането, има ситуации, когато се изисква да извършим многоредовата обработка.

В такива случаи статичните блокове са полезни.

Ако статичните променливи изискват допълнителна логика с много изрази по време на инициализация, тогава може да се използва статичен блок.

5.1. В статичен Блок пример

Да предположим, че искаме да инициализираме обект от списък с някои предварително дефинирани стойности.

Това става лесно със статични блокове:

public class StaticBlockDemo { public static List ranks = new LinkedList(); static { ranks.add("Lieutenant"); ranks.add("Captain"); ranks.add("Major"); } static { ranks.add("Colonel"); ranks.add("General"); } }

В този пример, това не би било възможно да се инициализира Списък обект с всички начални стойности, заедно с декларация; и затова използвахме статичния блок тук.

5.2. Принудителни причини за използване на статични блокове

  • Ако инициализацията на статични променливи изисква някаква допълнителна логика с изключение на присвояването
  • If the initialization of static variables is error-prone and requires exception handling

5.3. Key Points to Remember

  • A class can have multiple static blocks
  • static fields and static blocks are resolved and executed in the same order as they are present in the class

6. A static Class

Java programming language allows us to create a class within a class. It provides a compelling way of grouping elements that are only going to be used in one place, this helps to keep our code more organized and readable.

The nested class architecture is divided into two:

  • nested classes that are declared static are called static nested classes whereas,
  • nested classes that are non-static are called inner classes

The main difference between these two is that the inner classes have access to all member of the enclosing class (including private), whereas the static nested classes only have access to static members of the outer class.

In fact, static nested classes behaved exactly like any other top-level class but enclosed in the only class which will access it, to provide better packaging convenience.

6.1. Example of static Class

The most widely used approach to create singleton objects is through static nested class is it doesn't require any synchronization and is easy to learn and implement:

public class Singleton { private Singleton() {} private static class SingletonHolder { public static final Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.instance; } }

6.2. Compelling Reasons to Use a static Inner Class

  • Grouping classes that will be used only in one place increases encapsulation
  • The code is brought closer to the place that will be only one to use it; this increases readability and code is more maintainable
  • If nested class doesn't require any access to it's enclosing class instance members, then it's better to declare it as static because this way, it won't be coupled to the outer class and hence will be more optimal as they won't require any heap or stack memory

6.3. Key Points to Remember

  • static nested classes do not have access to any instance members of the enclosing outer class; it can only access them through an object's reference
  • статичните вложени класове могат да имат достъп до всички статични членове на затварящия клас, включително частни
  • Спецификацията за програмиране на Java не ни позволява да декларираме класа от най-високо ниво като статичен ; само класове в рамките на класовете (вложени класове) могат да бъдат направени като статични

7. Заключение

В тази статия видяхме статичната ключова дума в действие. Също така четем за причините и предимствата за използването на статични полета, статични методи, статични блокове и статични вътрешни класове.

Както винаги, можем да намерим пълния код на GitHub.