« poprzedni punkt  następny punkt »

2. Składowe statyczne
Składowe klasy to pola i metody.

Pola i metody klasy mogą być statyczne i niestatyczne.

Dotąd poznaliśmy tylko jeden rodzaj składowych - składowe niestatyczne.

Składowe niestatyczne zawsze wiążą się z istnieniem jakiegoś obiektu (pola - reprezentują dane obiektu, metody muszą być wywoływane na rzecz obiektu, określają polecenia wysyłane do obiektu)

Składowe statyczne (pola i metody):
  • są deklarowane przy użyciu specyfikatora static
  • mogą być używane nawet wtedy, gdy nie istnieje żaden obiekt klasy

Do statycznych składowych możemy odwoływać się za pomocą konstrukcji:

NazwaKlasy.NazwaSkładowej

Np. w klasie System (dostarczanej jako klasa standardowa w dystrybucji Java SDK 2) jest statyczna metoda exit(int) kończąca działanie aplikacji i zwracająca podany kod powrotu (wynik działania aplikacji).

Zatem, aby zakończyć działanie aplikacji z kodem powrotu 0 piszemy:

System.exit(0);

Korzystaliśmy już z metod uwidaczniania dialogów. Otóż dziwne zapisy np:

            JOptionPane.showInputDialog("Podaj dane")
            JOptiomPane.showMessageDialog(null, "Komuniakt")

znajdują teraz proste wyjaśnienie: mamy oto klasę JOptionPane (również w standardzie Javy). Metody showInputDialog(...)  i showMessageDialog(..) sa w niej zdefiniowane jako metody statyczne (ze specyfikatorem static), zatem odwołanie do nich możliwe jest za pomocą nazwy klasy - JOptionPane.

Z kolei metoda parseInt, służąca do przekształacania napisów na liczby całkowite jest statyczną metodą klasy Integer, dlatego pisaliśmy:

            Integer.parseInt("123");

No i najboleśniejsza zagadka (bolesna, bo jakże męczące jest pisanie System.out.println(...).
W klasie System jest stała statyczna o nazwie out, która określa obiekt - konsolę (standardowe wyjście). Temu obiektowi możemy wydać polecenie println, co spowoduje wyprowadzenie podanego argumentu jako napisu na konsolę (println jest metodą z klasy PrintStream, a out oznacza obiekt-konsolę, który jest obiektem klasy PrintStream).
Co więcej, metody println(...) są w klasie PrintStream przeciążone tzn. mają te same nazwy ale inne typy argumentów (String, int, double itd.)

Zobaczmy. Schematyczna deklaracja stalej statycznej out w klasie System wygląda tak:

public class System {
       ...
       public final static PrintStream out;
       ...
}

W klasie PrintStream (też dostępnej  jako jedna ze standardowych klas Javy) zdefiniowano metody println, która wypisuje do strumienia wyjściowego (PrintStream) podane argumenty.

public class PrintStream  {
       ...
       public void println(String s) {
       ...
       }

       public void println(int i) {
       ...
      }
}

Zatem, po kolei:

  • System.out - jest statycznym polem klasy System o identyfikatorze out; zmienna ta zawiera referencję do standardowej konsoli - konkretnego obiektu klasy PrintStream
  • println - ozncza użycie metody na rzecz tego obiektu.

W sumie: System.out.println(...).

Ze specyfikatorem static można deklarowac tylko zmienne, będące polami klasy

Bardzo ważną kwestią jest uświadomienie sobie różnicy pomiędzy składowymi statycznymi i niestatycznymi.

Można powiedzieć, że składowe statyczne stanowią właściwości całej klasy, a nie poszczególnych jej obiektów.
W przypadku pól rozróżnienie jest następujące:

  • pola niestatyczne istnieją (jako elementy) w każdym obiekcie klasy
  • pola statyczne - nie są zawarte w obiektach, dla każdej zmiennej statycznej wydzielany jest tylko jeden obszar pamięci na całą klasę

Na przykład, w klasie opisującej dyski będziemy mieli pole statyczne vat (stawka vat) oraz pola niestatyczne model (opis modelu dysku), capacity (pojemność w MB), price (cenę netto). Każdy dysk będzie się różnił modelem, pojemnością i ceną netto (zatem te elementy będą stanowiły zawartość obiektów), natomiast stawka vat dla wszystkich dysków jest taka sama - nie ma więc sensu zapisywac jej w każdym obiekcie, będzie ona wspólną właściwością klasy, a jako zmienna statyczna - będzie zajmowac tylko 8 bajtów na całą klasę, niezależnie od tego czy w programie stworzymy 1 czy 10000 obiektów - dysków.

public class Disk  {

  private static double vat;

  private String model;
  private int capacity;
  private double price;

  public Disk(String m, int c, double p) {
    model = m;
    capacity = c;
    price = p;
  }

  public String getDescription() {
    return model + " ," + capacity + " MB";
  }

  public double getBruttoPrice() {
    return price * ( 1 +  vat/100 );
  }

  public static void setVat(double v) {
    vat = v;
  }

}

class Test {

  public static void main(String[] args) {
    Disk.setVat(22.0);
    Disk d1 = new Disk("IBM598", 6040, 430.0);
    System.out.println(d1.getDescription() + " - cena "
                       + d1.getBruttoPrice() + " zł");
  }


IBM598 ,6040 MB - cena 524.6 zł


Zwróćmy uwagę, że metodę setVat wywołaliśmy przed stworzeniem jakiegokolwiek obiektu i pole vat uzyskalo wartość, mimo, że żaden obiekt nie istniał.


Ze statycznych metod nie wolno odwoływać się do niestatycznych składowych klasy (obiekt może nie istnieć). Możliwe są natomiast odwołania do innych statycznych składowych, np. innych metod statycznych.

ProblemZauważmy też, że z metod niestatycznych możemy w sposób naturalny odwoływac się do składowych (pól i metod) statycznych, co widac wyraźnie w metodzie getBruttoPrice().



« poprzedni punkt  następny punkt »