Statyczne i niestatyczne elementy klasy (static vs. non-static)
Elementy (atrybuty i metody) statyczne są powiązane z klasą, a elementy nie-statyczne są powiązane z konkretnymi obiektami - instancjami klasy.
Atrybut statyczny lub metoda statyczna jest nazywana odpowiednio atrybutem klasy oraz metodą klasy,
natomiast atrybut nie-statyczny lub metoda nie-statyczna jest nazywana odpowiednio atrybutaem obiektu oraz metodą obiektu danej klasy.
W programie obiektowym w Javie klasa jako "szablon" obiektów jest już sama w sobie istniejącym bytem - strukturą, z której możemy skorzystać, jeśli są w niej dostępne atrybuty klasy (atrybuty statyczne) i/lub metody klasy (metody statyczne).
Czyli jeśli mamy klasę i utworzymy obiekt tej klasy, to w rzeczywistości mamy już do dyspozycji w programie dwa elementy:
- klasę jako strukturę szablonu z dostępnymi atrybutami statycznymi i metodami statycznymi,
- obiekt tej klasy utworzony zgodnie z tym szablonem, w którym mamy dodatkowo dostęp do atrybutów niestatycznych i metod niestatycznych (atrybutów i metod obiektu), przy czym w obiekcie dostępne są także wszystkie elementy statyczne.
Do elementów statycznych mamy dostęp nawet bez tworzenia obiektu danej klasy. Dostęp do elementów statycznych uzyskujemy poprzez klasę - np. w pokazanym niżej przykładzie (zwróć uwagę na wielką literę oznaczającą nazwę klasy KlasaA):
KlasaA.trzeciaMetodaStatyczna();
Dlatego w metodach statycznych możemy korzystać wyłącznie z elementów statycznych (atrybutów i metod typu static).
Metody i atrybuty statyczne to tzw. metody i atrybuty klasy (a nie obiektu).
Do elementów nie-statycznych nie mamy dostępu, dopóki nie utworzymy obiektu danej klasy - czyli instancji klasy. Dopiero w konkretnym obiekcie danej klasy można uzyskać dostęp do elementów nie-statycznych (atrybutów i metod, dla których nie użyto słowa kluczoweto static). Zwróć uwagę, że wywołujemy metodę obiektu obiekt.
KlasaA obiekt = new KlasaA();
obiekt.drugaMetodaNIESTATYCZNA();
W metodach nie-statycznych możemy korzystać zarówno z elementów nie-statycznych jak i elementów statycznych.
Metody i atrybuty nie-statyczne to metody i atrybuty obiektu - konkretnego egzemplarza (instancji) klasy.
Modyfikując atrybut statyczny klasy, zmieniamy wartość tego atrybutu w "szablonie" i zmiana ta jest widoczna we wszystkich obiektach tej klasy.
Przykład użycia metod statycznych i nie-statycznych. Próba użycia metody nie-statycznej wewnątrz statycznej metody main powoduje błąd kompilacji.
public class KlasaA {
public static void main( String[] argumenty ) {
KlasaA.trzeciaMetodaStatyczna(); // wywołanie metody statycznej z klasy - UDANE
//drugaMetodaNIESTATYCZNA(); // próba wywołania metody NIEstatycznej ze statycznej metody main() - zakończona błędem kompilacji
//KlasaA.drugaMetodaNIESTATYCZNA(); // próba wywołania metody NIEstatycznej z klasy - zakończona błędem kompilacji
KlasaA obiektKlasyA = new KlasaA(); // utworzenie obiektu
obiektKlasyA.drugaMetodaNIESTATYCZNA(); // wywołanie metody NIEstatycznej z obiektu, a nie klasy - UDANE
obiektKlasyA.trzeciaMetodaStatyczna(); // wywołanie metody statycznej z obiektu, a nie klasy - UDANE
}
void drugaMetodaNIESTATYCZNA() { // metoda NIEstatyczna - metoda obiektu - instancji klasy
System.out.println("WYWOŁANO DRUGĄ METODĘ - niestatyczną");
}
static void trzeciaMetodaStatyczna() { // metoda statyczna - metoda klasy
System.out.println("WYWOŁANO TRZECIĄ METODĘ - statyczną");
}
}
Zauważ, że z obiektu możemy wywoływać metody zarówno statyczne jak i nie-statyczne. To samo dotyczy atrybutów - z obiektu mamy dostęp do atrybutów i metod zarówno nie-statycznych jak i statycznych.
Natomiast za pośrednictwem klasy możemy wywołać wyłącznie metody statyczne oraz uzyskać dostęp wyłącznie do atrybutów statycznych.
Dowód na to, że klasa jest "szablonem" i zmiana atrybutu statycznego jest widoczna we wszystkich obiektach utworzonych w oparci o ten "szablon". Zmieniając wartość atrybutu statycznego, zmieniamy ją dla wszystkich obiektów danej klasy. W pokazanym niżej przykładzie w obiekcie obiekt1 zmieniamy wartość statycznego atrybutu i natychmiast widać tę zmianę w obiekcie obiekt2:
UWAGA! Pokazany niżej kod kompiluje się przy użyciu kompilatora Java 8, natomiast w nowszej wersji Java 9 występuje błąd. Komunikat o błędzie nakazuje użycia nazwy klasy zamiast nazwy obiektu w odniesieniu do atrybutu statycznego - czyli np. nakazuje wpisać MojaKlasa.atrybutStatyczny zamiast obiekt1.atrybutStatyczny.
class MojaKlasa {
static int atrybutStatyczny;
int atrybutNiestatyczny;
}
public class Main {
public static void main( String... args ) {
MojaKlasa.atrybutStatyczny = 2;
System.out.println( "MojaKlasa.atrybutStatyczny == " + MojaKlasa.atrybutStatyczny );
MojaKlasa obiekt1 = new MojaKlasa();
MojaKlasa obiekt2 = new MojaKlasa();
System.out.println( "obiekt2.atrybutStatyczny == " + obiekt2.atrybutStatyczny );
obiekt1.atrybutStatyczny = 11;
System.out.println( "obiekt2.atrybutStatyczny == " + obiekt2.atrybutStatyczny );
}
}