Menu

Konstruktory w Javie: inicjalizacja obiektów przez new

Jak działają konstruktory w Javie: konstruktor domyślny, konstruktory z parametrami, this, przeciążanie konstruktorów i łańcuchowanie przez this() i super().

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

Po co są konstruktory

Na poprzedniej stronie budowałeś klasy i tworzyłeś obiekty przez new. Konstruktor to kod, który faktycznie wykonuje się podczas wywołania new. Jego jedynym celem jest zwrócenie obiektu gotowego do użycia: ze wszystkimi wymaganymi polami ustawionymi i bez częściowo zainicjalizowanego stanu.

Konstruktor wygląda jak metoda, ale z dwiema różnicami: ma taką samą nazwę jak klasa i nie ma typu zwracanego, nawet void.

new Point(3, 4) przydziela pamięć na obiekt, a potem wykonuje ciało konstruktora z x = 3 i y = 4. Zanim new zwróci wynik, p jest w pełni zainicjalizowany.

Słowo kluczowe this

W konstruktorze powyżej parametry nazywają się x i y, tak samo jak pola. this.x oznacza „pole x należące do tego obiektu”, a samo x odnosi się do parametru. Bez this zapis x = x przypisałby parametr samemu sobie i nie zmieniłby pola.

this jest konieczne tylko wtedy, gdy parametr przesłania pole, ale wiele osób używa go wszędzie dla przejrzystości. Częsty błąd to zapomnienie o nim przy kolizji nazw: kod się kompiluje, działa i po cichu zostawia pola z wartościami domyślnymi (null, 0, false).

Konstruktor domyślny

Jeśli nigdy nie napiszesz konstruktora, Java po cichu dostarcza konstruktor domyślny: publiczny, bezargumentowy konstruktor, który nie robi nic dodatkowego. Dlatego new działało dla klas, które w ogóle nie miały konstruktora.

Haczyk: gdy tylko napiszesz jakikolwiek konstruktor, darmowy znika.

class Box {
    int size;

    Box(int size) {       // teraz NIE ma konstruktora bezargumentowego
        this.size = size;
    }
}

new Box();   // błąd kompilacji: nie istnieje konstruktor Box()

Jeśli nadal chcesz, by działało new Box(), sam zadeklaruj konstruktor bezargumentowy:

Przeciążanie konstruktorów

Klasa może mieć kilka konstruktorów, o ile różnią się listą parametrów: to po prostu przeciążanie metod zastosowane do konstruktorów. Każdy z nich oferuje inny sposób zbudowania obiektu.

Java wybiera pasujący konstruktor na podstawie liczby i typów argumentów przekazanych do new.

Łańcuchowanie przez this()

Zauważ powtórzenia powyżej: każdy konstruktor sam przypisuje pola. Możesz tego uniknąć, gdy jeden konstruktor wywołuje inny przez this(...). To wywołanie musi być pierwszą instrukcją w konstruktorze.

Teraz właściwa inicjalizacja jest w jednym miejscu. Mniejsze konstruktory tylko uzupełniają wartości domyślne i przekazują pracę dalej. Jeśli spróbujesz umieścić jakąś instrukcję przed this(...), kompilator to odrzuci.

Konstruktory i super()

Każdy konstruktor najpierw niejawnie wywołuje konstruktor nadklasy. Jeśli nic nie napiszesz, Java wstawia na początku ciała ukryte super() (bezargumentowy konstruktor nadklasy). Zaczniesz z tym pracować bezpośrednio, gdy zaczniesz tworzyć podklasy, a to temat następnej strony.

class Animal {
    String name;
    Animal(String name) { this.name = name; }
}

class Dog extends Animal {
    Dog(String name) {
        super(name);   // tu trzeba jawnie wywołać konstruktor rodzica
    }
}

Animal nie ma konstruktora bezargumentowego, więc Dog musi jawnie wywołać super(name): nie ma darmowego super(), na którym mógłby polegać. Podobnie jak this(), wywołanie super(...) musi być pierwszą instrukcją w konstruktorze.

Dalej: dziedziczenie

Konstruktory inicjalizują pojedynczy obiekt, ale super() już zasugerowało coś większego: klasy mogą budować na innych klasach i ponownie wykorzystywać ich pola, metody i konstruktory. Ta relacja, w której jedna klasa rozszerza inną, to dziedziczenie. Omawia je następna strona.

Najczęściej zadawane pytania

Czym jest konstruktor w Javie?

Konstruktor to specjalna metoda, która uruchamia się, gdy tworzysz obiekt przez new. Ma taką samą nazwę jak klasa i nie ma typu zwracanego (nawet void). Jego zadaniem jest nadanie nowemu obiektowi poprawnego stanu początkowego, zwykle przez przypisanie argumentów konstruktora do pól obiektu.

Czym różni się konstruktor od metody w Javie?

Konstruktor ma dokładnie taką samą nazwę jak klasa, nie deklaruje typu zwracanego i można go wywołać tylko przez new przy tworzeniu obiektu. Zwykła metoda ma własną nazwę, deklaruje typ zwracany (lub void) i wywołuje się ją na istniejącym obiekcie. Konstruktory inicjalizują, a metody wykonują pracę później.

Co się stanie, jeśli nie napiszę konstruktora w Javie?

Kompilator daje ci za darmo bezargumentowy konstruktor domyślny, który nie przyjmuje parametrów i nie robi nic poza niejawnym wywołaniem super(). Gdy jednak sam napiszesz jakikolwiek konstruktor, ten darmowy znika. Jeśli więc dodasz konstruktor z parametrami i nadal chcesz, by działało new Thing(), musisz jawnie zadeklarować konstruktor bezargumentowy.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ