Java konstruktor: ključ koji otvara vrata kreiranju Java objekata
U prethodnom poglavlju smo naučili o Java metodama, pa će prelazak na konstruktore biti mnogo lakši.
U Javi je konstruktor posebna vrsta metode koja se poziva kada se klasa instancira. Tek kada se konstruktor pozove, objekat dobija alocirani memorijski prostor. Svaki put kada napravite objekat ključnom rečju new, konstruktor se poziva barem jednom.
Ako u klasi ne vidite konstruktor, to ne znači da on ne postoji — on je izostavljen, jer kompajler klasi obezbeđuje podrazumevani konstruktor. Drugim rečima, Java ima dve vrste konstruktora: konstruktor bez argumenata i konstruktor sa argumentima.
Pazi, zove se konstruktor zato što objekat pri kreiranju mora preko konstruktora da inicijalizuje vrednosti — da opiše koja inicijalna stanja objekat ima.
01. Pravila za kreiranje konstruktora
Konstruktor mora da poštuje sledeća pravila:
- Ime konstruktora mora biti isto kao ime klase;
- Konstruktor nema povratni tip, uključujući void;
- Konstruktor ne može biti apstraktan (abstract), statički (static), konačan (final) niti sinhronizovan (synchronized).
Da ukratko pojasnimo poslednje pravilo.
- Pošto konstruktor ne može da nasledi potklasa, nema smisla ga modifikovati ključnim rečima final i abstract;
- Konstruktor služi za inicijalizaciju objekta, pa ga modifikovati ključnom reči static nema smisla;
- Više niti neće istovremeno kreirati isti objekat na istoj memorijskoj adresi, pa je modifikator synchronized nepotreban.
Sintaksa konstruktora je sledeća:
class class_name {
public class_name(){} // podrazumevani konstruktor bez argumenata
public ciass_name([paramList]){} // definisanje konstruktora sa listom parametara
…
// telo klase
}Vredi napomenuti da ako konstruktor deklarišete sa void, neće doći do greške pri kompiliranju, ali će Java taj tzv. „konstruktor“ tretirati kao običnu metodu.
/**
* WeChat pretraga "Chenmo Wang Er", odgovorite Java
*
* @author Chenmo Wang Er
* @date 2020/11/26
*/
public class Demo {
void Demo(){ }
}void Demo(){} deluje kao ispravan zapis konstruktora (isto ime kao klasa), ali je zapravo samo obična metoda koja ne poštuje konvencije — prvo slovo imena metode je veliko, telo metode je prazno i nije u pitanju podrazumevani konstruktor bez argumenata, što se može proveriti dekompilacijom bajtkoda.
public class Demo {
public Demo() {
}
void Demo() {
}
}Tek public Demo() {} je pravi konstruktor bez argumenata.
Međutim, konstruktor se može modifikovati modifikatorima prava pristupa (private, protected, public, default), koji određuju način kreiranja konstruktora.
02. Podrazumevani konstruktor
Ako konstruktor nema ni jedan parametar, onda je to podrazumevani konstruktor, poznat i kao konstruktor bez argumenata.
/**
* @author WeChat pretraga "Chenmo Wang Er", odgovorite ključnu reč PDF
*/
public class Bike {
Bike(){
System.out.println("Napravljen je jedan bicikl");
}
public static void main(String[] args) {
Bike bike = new Bike();
}
}U ovom primeru smo za klasu Bike napravili konstruktor bez argumenata koji se poziva kada kreiramo objekat.
Izlaz programa je sledeći:
Napravljen je jedan biciklUobičajeno, konstruktor bez argumenata se može izostaviti — mi programeri ne moramo eksplicitno da ga deklarišemo, već taj posao prepustimo kompajleru.

Koja je svrha podrazumevanog konstruktora? Zašto je prazan? To je oštro pitanje.
Svrha podrazumevanog konstruktora je pre svega da poljima objekta obezbedi podrazumevane vrednosti. Pogledaj sledeći primer i biće ti jasno.
/**
* @author Chenmo Wang Er, jedan zanimljiv programer
*/
public class Person {
private String name;
private int age;
public static void main(String[] args) {
Person p = new Person();
System.out.println("Ime " + p.name + " Uzrast " + p.age);
}
}Izlaz je sledeći:
Ime null Uzrast 0U gornjem primeru podrazumevani konstruktor inicijalizuje vrednosti name i age. Pošto je name tipa String, podrazumevana vrednost mu je null, a pošto je age tipa int, podrazumevana vrednost mu je 0. Bez podrazumevanog konstruktora ovaj posao ne bi bio izvodljiv.
03. Konstruktor sa argumentima
Konstruktor sa parametrima se naziva konstruktor sa argumentima, a parametara može biti jedan ili više. Takav konstruktor omogućava da se različitim objektima daju različite vrednosti. Naravno, mogu se dati i iste vrednosti.
/**
* @author Chenmo Wang Er, jedan zanimljiv programer
*/
public class ParamConstructorPerson {
private String name;
private int age;
public ParamConstructorPerson(String name, int age) {
this.name = name;
this.age = age;
}
public void out() {
System.out.println("Ime " + name + " Uzrast " + age);
}
public static void main(String[] args) {
ParamConstructorPerson p1 = new ParamConstructorPerson("Chenmo Wang Er",18);
p1.out();
ParamConstructorPerson p2 = new ParamConstructorPerson("Chenmo Wang San",16);
p2.out();
}
}U gornjem primeru konstruktor ima dva parametra (name i age), pa pri kreiranju objekta možemo neposredno dodeliti vrednosti za name i age.
new ParamConstructorPerson("Chenmo Wang Er",18);
new ParamConstructorPerson("Chenmo Wang San",16);Da ne postoji konstruktor sa argumentima, poljima bismo morali da dodeljujemo vrednosti preko setter metoda.
04. Preopterećenje konstruktora
U Javi je konstruktor sličan metodi, samo nema povratni tip. Kao i metoda, može se preopteretiti. Preopterećenje konstruktora je jednostavno — dovoljno je navesti različite liste parametara. Kompajler na osnovu broja parametara odlučuje koji konstruktor treba pozvati.
/**
* @author Chenmo Wang Er, jedan zanimljiv programer
*/
public class OverloadingConstrutorPerson {
private String name;
private int age;
private int sex;
public OverloadingConstrutorPerson(String name, int age, int sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public OverloadingConstrutorPerson(String name, int age) {
this.name = name;
this.age = age;
}
public void out() {
System.out.println("Ime " + name + " Uzrast " + age + " Pol " + sex);
}
public static void main(String[] args) {
OverloadingConstrutorPerson p1 = new OverloadingConstrutorPerson("Chenmo Wang Er",18, 1);
p1.out();
OverloadingConstrutorPerson p2 = new OverloadingConstrutorPerson("Chenmo Wang San",16);
p2.out();
}
}Pri kreiranju objekta, ako se prenesu tri parametra, pozvaće se konstruktor OverloadingConstrutorPerson(String name, int age, int sex); ako se prenesu dva parametra, pozvaće se konstruktor OverloadingConstrutorPerson(String name, int age).
05. Razlika između konstruktora i metode
Razlika između konstruktora i metode je prilično velika, na primer u sledećem:

06. Kopiranje objekta
Kopiranje objekta se može obaviti na tri načina:
- preko konstruktora
- preko vrednosti objekta
- preko metode
clone()klase Object
1) Preko konstruktora
/**
* @author Chenmo Wang Er, jedan zanimljiv programer
*/
public class CopyConstrutorPerson {
private String name;
private int age;
public CopyConstrutorPerson(String name, int age) {
this.name = name;
this.age = age;
}
public CopyConstrutorPerson(CopyConstrutorPerson person) {
this.name = person.name;
this.age = person.age;
}
public void out() {
System.out.println("Ime " + name + " Uzrast " + age);
}
public static void main(String[] args) {
CopyConstrutorPerson p1 = new CopyConstrutorPerson("Chenmo Wang Er",18);
p1.out();
CopyConstrutorPerson p2 = new CopyConstrutorPerson(p1);
p2.out();
}
}U gornjem primeru postoji konstruktor čiji je parametar tipa CopyConstrutorPerson koji može neposredno da kopira polja tog parametra u novi objekat, tako da prilikom kreiranja novog objekta ključnom reči new možemo proslediti prethodni objekat p1.
2) Preko vrednosti objekta
/**
* @author Chenmo Wang Er, jedan zanimljiv programer
*/
public class CopyValuePerson {
private String name;
private int age;
public CopyValuePerson(String name, int age) {
this.name = name;
this.age = age;
}
public CopyValuePerson() {
}
public void out() {
System.out.println("Ime " + name + " Uzrast " + age);
}
public static void main(String[] args) {
CopyValuePerson p1 = new CopyValuePerson("Chenmo Wang Er",18);
p1.out();
CopyValuePerson p2 = new CopyValuePerson();
p2.name = p1.name;
p2.age = p1.age;
p2.out();
}
}Ovaj način je prilično grub — uzima se vrednost polja objekta p1 i kopira u objekat p2 (p2.name = p1.name).
3) Preko metode clone() klase Object
/**
* @author Chenmo Wang Er, jedan zanimljiv programer
*/
public class ClonePerson implements Cloneable {
private String name;
private int age;
public ClonePerson(String name, int age) {
this.name = name;
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public void out() {
System.out.println("Ime " + name + " Uzrast " + age);
}
public static void main(String[] args) throws CloneNotSupportedException {
ClonePerson p1 = new ClonePerson("Chenmo Wang Er",18);
p1.out();
ClonePerson p2 = (ClonePerson) p1.clone();
p2.out();
}
}Pri kopiranju objekta metodom clone(), klasa ClonePerson prvo mora da implementira metodu clone() iz interfejsa Cloneable, a zatim da pozove metodu clone() (ClonePerson p2 = (ClonePerson) p1.clone()).
Dodatno čitanje: plitko i duboko kopiranje
07. Kraj
Da li mogu da te pitam nešto? Naravno, pitaj.
„Zar konstruktor zaista ne vraća nikakvu vrednost?“
„Iako konstruktor nema povratnu vrednost, on zapravo vraća objekat klase.“
„Da li konstruktor može samo da inicijalizuje polja?“
„Inicijalizacija polja je samo jedan od poslova konstruktora; on može raditi i mnogo više, na primer pokrenuti nit, pozvati druge metode i slično.“
Važi, to je sve od pitanja, današnje učenje možemo završiti!
Ne zaboravi da ponoviš sadržaj sledećeg poglavlja.
