Przewodnik po statycznym słowie kluczowym w Javie

1. Wstęp

W tym artykule szczegółowo omówimy statyczne słowo kluczowe języka Java. Dowiemy się, jak możemy zastosować słowo kluczowe static do zmiennych, metod, bloków, klas zagnieżdżonych i jakie ma to znaczenie.

2. Anatomia statycznego słowa kluczowego

W języku programowania Java słowo kluczowe static wskazuje, że dany element członkowski należy do samego typu, a nie do instancji tego typu .

Oznacza to, że tworzone jest tylko jedno wystąpienie tego statycznego elementu członkowskiego, które jest współużytkowane przez wszystkie wystąpienia klasy.

Słowo kluczowe można zastosować do zmiennych, metod, bloków i klas zagnieżdżonych.

3. Pola statyczne (lub zmienne klas)

W Javie, jeśli pole zostanie zadeklarowane jako statyczne , to utworzona zostanie dokładnie jedna kopia tego pola, która będzie współdzielona przez wszystkie instancje tej klasy . Nie ma znaczenia, ile razy inicjalizujemy klasę; zawsze będzie należała tylko jedna kopia pola statycznego . Wartość tego pola statycznego będzie wspólna dla wszystkich obiektów tego samego lub innej klasy.

Z punktu widzenia pamięci, zmienne statyczne trafiają do określonej puli pamięci JVM o nazwie Metaspace (przed Java 8 pula ta nosiła nazwę Permanent Generation lub PermGen, która została całkowicie usunięta i zastąpiona Metaspace).

3.1. Przykład pola statycznego

Załóżmy, że mamy klasę Car z kilkoma atrybutami (zmiennymi instancji) . Za każdym razem, gdy nowe obiekty są inicjowane z tego planu samochodu , każdy nowy obiekt będzie miał swoją odrębną kopię tych zmiennych instancji.

Załóżmy jednak, że szukamy zmiennej, która przechowuje liczbę zainicjowanych obiektów Car i jest współdzielona przez wszystkie instancje, tak aby mogły uzyskać do niej dostęp i zwiększać ją po inicjalizacji.

W tym miejscu pojawiają się zmienne statyczne :

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 }

Teraz dla każdego inicjalizowanego obiektu tej klasy ta sama kopia zmiennej numberOfCars jest zwiększana. W tym przypadku prawdziwe będą następujące stwierdzenia:

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

3.2. Istotne powody, dla których warto używać pól statycznych

  • Gdy wartość zmiennej jest niezależna od obiektów
  • Kiedy wartość ma być wspólna dla wszystkich obiektów

3.3. Kluczowe punkty do zapamiętania

  • Ponieważ zmienne statyczne należą do klasy, można uzyskać do nich bezpośredni dostęp za pomocą nazwy klasy i nie wymagają żadnego odwołania do obiektu
  • zmienne statyczne można deklarować tylko na poziomie klasy
  • Dostęp do pól statycznych można uzyskać bez inicjalizacji obiektu
  • Chociaż możemy uzyskać dostęp do pól statycznych za pomocą odwołania do obiektu (np. Ford.numberOfCars ++ ), powinniśmy powstrzymać się od tego, ponieważ w tym przypadku trudno jest określić, czy jest to zmienna instancji, czy zmienna klasy; zamiast tego powinniśmy zawsze odnosić się do zmiennych statycznych za pomocą nazwy klasy (na przykład w tym przypadku Car.numberOfCars ++ )

4. Metody statyczne (lub metody klasowe)

Podobny do statycznych pól statycznych metod również należą do klasy zamiast obiektu, a więc można nazwać bez tworzenia obiektu klasy, w którym zamieszkują. Mają być używane bez tworzenia obiektów klasy.

4.1. Przykład metody statycznej

Metody statyczne są zwykle używane do wykonywania operacji, które nie są zależne od tworzenia instancji.

Jeśli istnieje kod, który ma być współużytkowany we wszystkich instancjach tej klasy, napisz ten kod w metodzie statycznej :

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

Metody statyczne są również szeroko stosowane do tworzenia klas narzędziowych lub pomocniczych, dzięki czemu można je uzyskać bez tworzenia nowego obiektu tych klas.

Wystarczy spojrzeć na klasy narzędziowe Collections lub Math z JDK, StringUtils z Apache lub CollectionUtils z frameworka Spring i zauważ, że wszystkie metody są statyczne .

4.2. Istotne powody, dla których warto stosować metody statyczne

  • Aby uzyskać dostęp / manipulować zmiennymi statycznymi i innymi metodami statycznymi, które nie zależą od obiektów
  • metody statyczne są szeroko stosowane w klasach narzędziowych i pomocniczych

4.3. Kluczowe punkty do zapamiętania

  • metody statyczne w Javie są rozwiązywane w czasie kompilacji. Ponieważ przesłanianie metod jest częścią polimorfizmu środowiska uruchomieniowego, nie można zastąpić metod statycznych
  • metody abstrakcyjne nie mogą być statyczne
  • metody statyczne nie mogą używać tego ani super słów kluczowych
  • Obowiązują następujące kombinacje instancji, metod klas i zmiennych:
    1. Metody instancji mają bezpośredni dostęp zarówno do metod instancji, jak i zmiennych instancji
    2. Metody instancji może również dostęp statycznych zmiennych i statycznych metod bezpośrednio
    3. metody statyczne mogą uzyskać dostęp do wszystkich zmiennych statycznych i innych metod statycznych
    4. metody statyczne nie mają bezpośredniego dostępu do zmiennych instancji i metod instancji ; potrzebują do tego odniesienia do obiektu

5. Blok statyczny

Statyczny blok służy do inicjalizacji statycznych zmiennych. Chociaż zmienne statyczne można zainicjować bezpośrednio podczas deklaracji, są sytuacje, w których wymagane jest przetwarzanie wielowierszowe.

W takich przypadkach przydają się statyczne bloki.

Jeśli zmienne statyczne wymagają dodatkowej logiki złożonej z wielu instrukcji podczas inicjalizacji, można użyć bloku statycznego .

5.1. Statyczne bloku Przykład

Załóżmy, że chcemy zainicjować obiekt listy z pewnymi predefiniowanymi wartościami.

Staje się to łatwe w przypadku bloków statycznych :

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"); } }

W tym przykładzie nie byłoby możliwe zainicjowanie obiektu List ze wszystkimi wartościami początkowymi wraz z deklaracją; i dlatego wykorzystaliśmy tutaj blok statyczny .

5.2. Istotne powody, dla których warto używać bloków statycznych

  • Jeśli inicjalizacja zmiennych statycznych wymaga dodatkowej logiki oprócz przypisania
  • Jeśli inicjalizacja zmiennych statycznych jest podatna na błędy i wymaga obsługi wyjątków

5.3. Kluczowe punkty do zapamiętania

  • Klasa może mieć wiele bloków statycznych
  • pola statyczne i bloki statyczne są rozwiązywane i wykonywane w tej samej kolejności, w jakiej występują w klasie

6. Klasa statyczna

Język programowania Java pozwala nam tworzyć klasy w ramach klasy. Zapewnia fascynujący sposób grupowania elementów, które mają być używane tylko w jednym miejscu, co pomaga utrzymać nasz kod w lepszej organizacji i czytelności.

Zagnieżdżona architektura klas jest podzielona na dwie części:

  • klasy zagnieżdżone, które są zadeklarowane jako statyczne, nazywane są statycznymi klasami zagnieżdżonymi, natomiast
  • klasy zagnieżdżone, które nie są statyczne, nazywane są klasami wewnętrznymi

Główną różnicą między tymi dwoma jest to, że klasy wewnętrzne mają dostęp do wszystkich elementów członkowskich klasy otaczającej (w tym klasy prywatnej), podczas gdy statyczne klasy zagnieżdżone mają dostęp tylko do statycznych elementów członkowskich klasy zewnętrznej.

W rzeczywistości statyczne klasy zagnieżdżone zachowywały się dokładnie tak samo, jak każda inna klasa najwyższego poziomu, ale zostały zamknięte w jedynej klasie, która będzie miała do niej dostęp, aby zapewnić lepszą wygodę pakowania.

6.1. Przykład klasy statycznej

Najczęściej stosowanym podejściem do tworzenia obiektów singleton jest statyczna klasa zagnieżdżona, ponieważ nie wymaga żadnej synchronizacji i jest łatwa do nauczenia i wdrożenia:

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
  • statyczne klasy zagnieżdżone mogą uzyskać dostęp do wszystkich statycznych elementów członkowskich otaczającej klasy, w tym prywatnych
  • Specyfikacja programowania Java nie pozwala nam deklarować klasy najwyższego poziomu jako statycznej ; tylko klasy wewnątrz klas (klasy zagnieżdżone) mogą być ustawione jako statyczne

7. Wnioski

W tym artykule widzieliśmy słowo kluczowe static w akcji. Czytamy również o powodach i zaletach stosowania pól statycznych, metod statycznych, bloków statycznych i statycznych klas wewnętrznych.

Jak zawsze, cały kod możemy znaleźć na GitHub.