Metody statyczne
Na pewno spotkałeś/aś się z określeniem, że w Javie wszystko jest klasą. W rzeczywistości faktem jest, że każdy napisany przez nas kod MUSI zawierać się w jakiejś klasie. To wymuszenie sprawia, że Java faktycznie jest językiem w pełni obiektowym. Jednak jest sposób, aby pisać kod bez stosowania obiektów. Z pomocą przychodzą tu metody statyczne.
Przypomnij sobie proszę metodę main, dzięki której odpalić można program w Javie. Sygnatura takiej metody zawsze wygląda tak:
public static void main(String [] args)
W każdej metodzie main należy zawrzeć słowo kluczowe static. Umożliwia ono używanie metody bez tworzenia obiektu. Tak, nie przesłyszałeś/aś się, w Javie można używać metod w klasach bez uprzedniego stworzenia jej obiektu. Takie podejście nazywamy programowaniem strukturalnym a nie obiektowym. Popatrz na przykład poniżej.
public class StructuralProgramming { static void showMessage(String message) { System.out.println(message); } static int add(int valueOne, int valueTwo) { return valueOne + valueTwo; } } public class MainClass { static void main(String[] args) { int sum = StructuralProgramming.add(10, 20); System.out.println(sum); StructuralProgramming.showMessage("test message"); } }
Na konsoli wyświetli się:
30
test message
Modyfikator static
Metody statyczne możesz używać zawsze, gdy pozwoli Ci na to modyfikator dostępu (w przypadku, gdy jest to dostęp pakietowy, co oznacza, że każda klasa w pakiecie może jej używać). Aby wywołać metodę statyczną, nie tworzysz jej obiektu, wystarczy odwołać się do nazwy klasy i po kropce wybrać odpowiednią metodę. Jest to bardzo wygodne rozwiązanie, ale niestety, jak wszystko w życiu, ma swoją cenę.
Wyobraź sobie, że masz system, który zawiera miliony klas. Pracują nad nimi dziesiątki deweloperów rozsianych po całym świecie. Nagle każdy zaczyna używać sobie twojej metody statycznej bez deklaracji obiektu. Po paru dniach system przestał działać i nikt nie jest wstanie stwierdzić dlaczego, ponieważ metoda była używana globalnie, bez względu na to, czy tworzone po drodze obiekty faktycznie pozwalały na jej użycie. Sprawdzenie teraz kilkuset klas, gdzie użyto statycznej metody, zajęłoby programistom tygodnie, a firma w tym czasie zbankrutowała.
Dostrzegasz teraz niebezpieczeństwo używania takich metod? Są jednak sytuacje, kiedy warto używać statycznych (czyli klasowych) metod. Na przykład, gdy tworzysz bezstanową metodę pomocniczą, która liczy średnią ważoną. Metoda bezstanowa, to taka, która nie modyfikuje żadnych zmiennych referencyjnych (obiektów, tablic, itp.). Taką metodę możemy użyć zawsze w systemie bez obawy, że coś komuś przypadkiem nadpiszemy (na przykład poprzez podmienienie referencji, itp).
Programowanie obiektowe vs strukturalne
Abyś lepiej pojął różnice między programowaniem obiektowym i strukturalnym, spójrz proszę na ten przykład:
public class Car { String model; void showMeCar() { System.out.println("Car model is: " + model); } } public class StructuralProgramming { static void showMessage(String message) { Car car = new Car(null, 0); car.showMeCar(); System.out.println(message); } static int add(int valueOne, int valueTwo) { return valueOne + valueTwo; } }
Jak widzisz bez problemu można zagnieżdżać w metodach statycznych obiekty. Nie ma też żadnych problemów, aby statyczne metody wywoływać w metodach niestatycznych w obiektach. Problem zaczyna się, gdy zaczynasz mieszać metody statyczne i niestatyczne w jednej klasie.
public class StructuralProgramming { String name; static void showMessage(String message) { add(1,2); // Error: Cannot make a static reference to the non-static method System.out.println(message + " " + name); // Error: Cannot make a static reference to the non-static field name } int add(int valueOne, int valueTwo) { return valueOne + valueTwo; } }
Tak napisany kod się nie skompiluje. Dzieje się tak dlatego, że nie można używać zmiennych/metod niestatycznych (instancyjnych) w metodach statycznych. Przypominam raz jeszcze, że metody statyczne to metody klasowe i działają niezależnie od tworzonych obiektów tej klasy przez cały czas działania programu. Poniżej przedstawiam jak powinien wyglądać powyższy kod prawidłowo:
public class StructuralProgramming { static String name; static void showMessage(String message) { add(1,2); System.out.println(message + " " + name); } static int add(int valueOne, int valueTwo) { return valueOne + valueTwo; } }
Podsumowując, warto rozważyć używanie metod statycznych, w momencie, gdy nie chcesz przechowywać stanu w polach klasowych. Świetnie się sprawdzają się one, w miejscach, gdzie przetwarzasz w ciele metody jej argumenty i od razu zwracasz wynik.
Link do lekcji: https://github.com/developeronthego/java-basics/tree/main/src/main/java/basics/lesson5
Bardziej zaawansowane odnośnie stałych i statycznych pól: https://developeronthego.pl/java-srednio-zaawansowane-6-statyczne-pola-stale/