Konstruktory w Javie

opublikował: LukaszJakobczak, 2013-12-29

Pojecie konstruktorów, a przede wszystkim zrozumienie zasad ich działania, jest istotnym elementem programowania obiektowego, zatem w tym artykule chciałbym przybliżyć specjalne metody tworzące obiekty, czyli konstruktory. Przedstawię jak tworzyć i przeciążać konstruktory, ile argumentów mogą przyjmować i pokażę różnice pomiędzy domyślnym konstruktorem, a tym zdefiniowanym przez użytkownika.

Konstruktory, to specjalne metody, które tworzą obiekty klasy, w której się znajdują
i, co ważne, nie posiadają one żadnego typu zwrotnego. Po utworzeniu obiektu przy użyciu operatora new wszystkie jego zmienne przyjmują wartości domyślne, ale co jeśli programista chciałby by te zmienne zawierały jakieś konkretne wartości? Tutaj przychodzą z pomocą konstruktory.

Konstruktory występują w dwóch formach: domyślnej i zdefiniowanej przez użytkownika. Na początek zajmę się konstruktorem domyślnym:

class Uczen {

       String imie;

       int wiek;

}

 

Powyższa klasa nie zawiera żadnego konstruktora, ale wciąż można tworzyć obiekty tej klasy w innej klasie:

 

class Szkola {

       public static void main(String[] args){

             Uczen uczen = new Uczen();

       }

}

 

W tym przypadku, przy braku konstruktora zdefiniowanego przez użytkownika kompilator Javy tworzy bezargumentowy konstruktor domyślny, który przypisuje domyślne wartości wszystkim zmiennym w klasie wywoływanej (String imie = null, int wiek = 0). W przypadku gdy programista doda swój konstruktor do klasy, kompilator Javy usunie ten domyślny.

 

            W większości przypadków chce się jednak, aby zmienne zawierały konkretne wartości, wtedy należy zdefiniować własny konstruktor. Przyjrzyjmy się raz jeszcze klasie Uczen:

 

class Uczen {

       String imie;

       int wiek ;

       Uczen(){

             imie = "Jacek";

             wiek = 15;

       }

}

 

W powyższym przykładzie użytkownik zdefiniował swój własny, bezargumentowy konstruktor w klasie Uczen.

 

class Szkola {

       public static void main(String[] args){

             Uczen uczen = new Uczen();

       }

}

 

Nowy uczeń „stworzony” przy pomocy operatora new będzie miał na imię Jacek i będzie miał 15 lat. Ale co w przypadku jeśli chcielibyśmy utworzyć listę wszystkich uczniów w szkole? Statystycznie pojawiłoby się kilku Jacków, ale co z pozostałymi uczniami? Rozwiązanie jest proste, ponieważ konstruktory to metody można im przekazywać różne parametry. Zmieńmy teraz klasę Uczen, aby zawierała zdefiniowany przez użytkownika konstruktor dwuargumentowy:

 

class Uczen {

       String imie;

       int wiek ;

       Uczen(String noweImie, int nowyWiek){

             imie = noweImie;

             wiek = nowyWiek;

       }

}

 

Z tak przygotowaną klasą ucznia, możemy „tworzyć” nowych uczniów, nadając im ich imiona i wiek, które są przekazane jako parametry:

 

class Szkola{

       public static void main(String[] args){

             Uczen uczen = new Uczen("Marek", 15);

             Uczen uczen2 = new Uczen("Asia", 14);

       }

}

 

Konstruktor jest wywoływany, kiedy jest tworzony obiekt danej klasy, zatem tworzy on i zwraca obiekt danej klasy, dlatego nie definiujemy dla konstruktorów typów zwrotnych
tak, jak w przypadku zwykłych metod. Jeśli zdefiniujemy w konstruktorze typ zwrotny zostanie on potraktowany przez Jave jako zwykła metoda, pomimo takiej samej nazwy jak klasa, zatem nie będzie wywoływany przy tworzeniu obiektów danej klasy. Powyższa klasa Szkola tworzy dwa obiekty klasy Uczen.

 

            Konstruktory mogą przyjmować wiele argumentów. Powyżej były przykłady bezargumentowego, jak i dwuargumentowego konstruktora. Mogą one przyjmować też więcej argumentów.  Poniżej przykład wieloargumentowego konstruktora w klasie Uczen jak i klasa Szkola tworząca obiekt klasy Uczen:

 

class Uczen {

       String imie;

       String nazwisko;

       int wiek ;

       String adres;

       Uczen(String noweImie, String noweNazwisko, int nowyWiek, String nowyAdres){

             imie = noweImie;

             nazwisko = noweNazwisko;

             wiek = nowyWiek;

             adres = nowyAdres;

       }

}

 

class Szkola {

       public static void main(String[] args){

             Uczen uczen = new Uczen("Mateusz", "Nowak", 15, "ul. Nowa 14");

       }

}

 

            W taki sam sposób, w jaki można przeciążać metody, można tez przeciążać i konstruktory. Tworzy je się na takich samych regułach. Muszą one być stworzone używając innych argumentów i nie mogą być stworzone tylko za zmianą specyfikatora dostępu. Zaprezentuje to na przykładzie klasy Uczen:

 

class Uczen {

       String imie;

       int wiek;

       Uczen(){

             imie = "Wojtek";

             wiek = 15;

       }

       Uczen(String noweImie){

             imie = noweImie;

             wiek = 16;

       }

       Uczen(String noweImie, int nowyWiek){

             imie = noweImie;

             wiek = nowyWiek;

       }

       Uczen(int nowyWiek, String noweImie){

             imie = noweImie;

             wiek = nowyWiek;

       }

}

 

Powyższa klasa prezentuje odpowiednio bezargumentowy konstruktor, jednoargumentowy konstruktor i dwa przeciążone (za sprawą innej pozycji argumentów) dwuargumentowe konstruktory.

 

            Wielokrotnie klasy posiadają wiele konstruktorów i, w przeciwieństwie do przeciążonych metod, przeciążone konstruktory wywołuje się z innych konstruktorów za pomocą słowa kluczowego this:

 

class Uczen {

       String imie;

       int wiek;

       Uczen(){

             this(null, 0);

       }

       Uczen(String noweImie, int nowyWiek){

             imie = noweImie;

             wiek = nowyWiek;

       }

}

 

W przypadku braku parametrów bezargumentowy konstruktor wywoła dwuargumentowy konstruktor i przekaże mu (jako parametry) wcześniej zdefiniowane przez programistę wartości. Słowo kluczowe this musi być pierwszym w konstruktorze, aby się poprawnie skompilował.

 

            Podsumowując,  konstruktory to specjalne metody tworzące i zwracające obiekt danej klasy, maja one taką nazwę jak klasa i nie zdefiniowany typ zwrotny, nawet void. Jeśli zdefiniujemy typ zwrotny dla konstruktora będzie on traktowany jak zwykła metoda. Przeciążone konstruktory musza być zdefiniowane za pomocna różnych argumentów (nawet takich samych tylko na innych pozycjach) i nie mogą być zdefiniowane tylko za pomocą zmiany specyfikatora dostępu. Konstruktor może wywołać inny konstruktor z pomocą słowa kluczowego this. Zajmując się programowaniem w Javie programista będzie miał do czynienia cały czas z konstruktorami. Zrozumienie zasad ich działania jest bardzo istotne dla posługiwania się programowaniem obiektowym.

 

 

 

Bibliografia:

 

1.      http://docs.oracle.com/javase/tutorial/java/javaOO/index.html [dostęp w dniu: 29.12.2013].

2.      „Java Podstawy” , Cay S. Horstmann, Gary Cornell, HELION 2008.

3.      “Java Praktyczny Kurs”, Marcin Lis, HELION 2011.

4.      „OCA Java SE 7 Certification Guide”, Mala Gupta, MANNING 2013.