Java#23: pola statyczne i stałe

Pola statyczne i metody

Pamiętasz pewnie z kursu dotyczącego podstaw programowania, że alternatywą dla programowania obiektowego jest programowanie strukturalne (oparte na metodach statycznych). Każda metoda statyczna (czyli klasowa) musi zawierać wszystkie wewnętrzne komponenty (użyte inne metody czy pola) statyczne. O ile używanie statycznych metod w innych metodach statycznych jest jak najbardziej logiczne, o tyle, możesz nie rozumieć jeszcze czym są pola statyczne i dlaczego one istnieją.

Celem deklaracji statycznego pola (np. private static int counter;) jest przetrzymywanie jakiś wartości zmiennej w pamięci (możesz porównać to do funkcjonowania pamięci cache w komputerze*). Oznacza to, że kiedy przypiszesz wartość do pola typu static to wirtualna maszyna Javy zachowa ją w pamięci tak długo póki będzie ona działać na Twoim systemie operacyjnym. Oczywiście możesz to pole dowolnie nadpisywać (nie myl static ze słowem final).  Pola statyczne mogą działać zarówno z typami prostymi (int, float, itp.) oraz z typami referencyjnymi (np. obiekty).

public class Restaurant {
  private String name;
  
  public Restaurant(String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }	
}
public final class RestaurantHelper {
  private static Restaurant[] restaurants =  new Restaurant [100];
  private static int restaurantsCounter = 0;
  
  public static void showRestaurants() {
    for (int i = 0; i < restaurantsCounter; i++) {
      System.out.println(restaurants[i].getName());
    }
  }
  
  public static void add(Restaurant restaurant) {
    restaurants[restaurantsCounter] = restaurant;
    restaurantsCounter++;
    System.out.println("New restaurant added.");
  }
  
}

Działanie pól statycznych

Klasa RestaurantHelper zawiera dwa pola statyczne: tablicę restauracji oraz licznik restauracji. Metoda showRestaurants pokazuje wszystkie wszystkie zapisane restauracje. Metoda add dodaje nową restaurację.  Ponieważ za każdym razem do poprawnego wyświetlenia wszystkich restauracji musimy znać liczbę zapisanych rekordów, to po każdym wpisie należy zwiększyć licznik restaurantsCounter. Dodatkowo zauważ, że maksymalna liczba restauracji, którą możesz zapisać to 100 (w kolejnych lekcjach pokażę Ci strukturę, która rozwiązuje ten problem).

Tworzenie stałych

Możesz też stworzyć zmienną klasową, która będzie publiczna, statyczna i finalna. Klasa zawierająca takie pola, przypomina trochę typ wyliczeniowy (enum). Jest dobrze przyjęte, żeby wszelkie napisy wyrzucać do zmiennych typu String. Posiadając taką klasę ze zmiennymi globalnymi, możesz ja łatwo użyć w każdej  innej klasie w swoim projekcie.

public final class RestaurantNames {
  public static final String MC_DONALDS = "Mc Donald's";
  public static final String KFC = "KFC";
  public static final String PIZZA_HUT = "Pizza Hut";
}

Spróbuj teraz odpalić poniższy main, który dodaje trzy różne restauracje do statycznej tablicy, po czym je wyświetla. Zauważ, że nie korzystam tu z programowania obiektowego tylko strukturalnego (mam na myśli oczywiście klasę RestaurantHelper, a nie obiekty Restaurant).

public class StaticsMain {

  public static void main(String[] args) {
    Restaurant mcDonalds = new Restaurant(RestaurantNames.MC_DONALDS);
    Restaurant kfc = new Restaurant(RestaurantNames.KFC);
    Restaurant pizzaHut = new Restaurant(RestaurantNames.PIZZA_HUT);
    
    RestaurantHelper.add(mcDonalds);
    RestaurantHelper.add(kfc);
    RestaurantHelper.add(pizzaHut);
    
    RestaurantHelper.showRestaurants();
  }

}

Statyczne importy

Poniżej pokazałem implementację, tego samej klasy main, ale z użyciem statycznych importów. Różnica jest taka, że teraz kod trochę krótszy, co jest zgodne  z regułą DRY (Don’t Repeat Yourself).

import static advanced.statics.RestaurantNames.KFC;
import static advanced.statics.RestaurantNames.MC_DONALDS;
import static advanced.statics.RestaurantNames.PIZZA_HUT;

import static advanced.statics.RestaurantHelper.add;
import static advanced.statics.RestaurantHelper.showRestaurants;

public class StaticImportsMain {

  public static void main(String[] args) {
    Restaurant mcDonalds = new Restaurant(MC_DONALDS);
    Restaurant kfc = new Restaurant(KFC);
    Restaurant pizzaHut = new Restaurant(PIZZA_HUT);
    
    add(mcDonalds);
    add(kfc);
    add(pizzaHut);
    
    showRestaurants();
  }
}

Używanie stałych czy importów statycznych jest proste. Gorzej, jeśli chodzi o poprawne użycie pól statycznych. Teoretycznie wszystko wygląda prosto, ale korzystanie z nich w skomplikowanych systemie stwarza wiele problemów związanych z wielowątkowością. Pomyśl np. co się stanie gdy, jedna klasa będzie próbować zwiększać taki statyczny licznik a druga go zmniejszać. Na pewno rozumiesz, że takie działanie jest niepożądane, ale na odpowiedź jak sobie z tym radzić musisz poczekać, aż stworzę mini kurs związany tylko i wyłącznie z obsługą wielu wątków w Javie.

Podsumowane:

  • Pola statyczne inicjalizuje się poprzez: private static ..
  • Statyczne zmienne globalne, używając: public static ..
  • Stałe dostępne tylko dla klasy: private final static ..
  • Stałe globalne: public final static ..
  • Importy statyczne: import static ..

*https://pl.wikipedia.org/wiki/Pamięć_podręczna

Link do lekcji: https://github.com/developeronthego/java-middle/tree/master/src/main/java/middle/lesson6

Lekcja odnośnie zwykłych importów: https://developeronthego.pl/java-podstawy-13-importy-i-pakiety/

Stay in the Loop

Get the daily email from CryptoNews that makes reading the news actually enjoyable. Join our mailing list to stay in the loop to stay informed, for free.

Ostatnio dodane

- Advertisement - spot_img

Powiązane wpisy