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.
Zauważ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().
|