Vodič za konstruktore na Javi

1. Uvod

Konstruktori su čuvari vrata objektno orijentirani dizajn.

U ovom uputstvu vidjet ćemo kako djeluju kao jedno mjesto s kojeg se inicijalizira unutarnje stanje objekta koji se stvara.

Krenimo unaprijed i stvorimo jednostavan objekt koji predstavlja bankovni račun.

2. Postavljanje bankovnog računa

Zamislite da trebamo stvoriti klasu koja predstavlja bankovni račun. Sadržat će ime, datum nastanka i stanje.

Također, poništimo toString metoda za ispis detalja na konzolu:

klasa BankAccount {Naziv niza; LocalDateTime otvoren; dvostruka ravnoteža; @Override public String toString () {return String.format ("% s,% s,% f", this.name, this.opened.toString (), this.balance); }} 

Sada ova klasa sadrži sva potrebna polja potrebna za pohranu podataka o bankovnom računu, ali još ne sadrži konstruktor.

To znači da ako kreiramo novi objekt, vrijednosti polja ne bi bile inicijalizirane:

Račun BankAccount = novi BankAccount (); account.toString (); 

Pokretanje toString gornja metoda rezultirat će iznimkom jer objekti Ime i otvorio još uvijek null:

java.lang.NullPointerException na com.baeldung.constructors.BankAccount.toString (BankAccount.java:12) na com.baeldung.constructors.ConstructorUnitTest .givenNoExplicitContructor_whenUsed_thenFails (ConstructorUnitTest.java 

3. Konstruktor bez argumenata

Popravimo to konstruktorom:

klasa BankAccount {public BankAccount () {this.name = ""; this.opened = LocalDateTime.now (); this.balance = 0.0d; }} 

Primijetite nekoliko stvari o konstruktoru koje smo upravo napisali. Prvo, to je metoda, ali nema povratni tip. To je zato što konstruktor implicitno vraća vrstu objekta koji stvara. Pozivanje novi BankAccount () sada će pozvati konstruktor gore.

Drugo, nema argumenata. Ova posebna vrsta konstruktora naziva se nkonstruktor o-argumenata.

Zašto nam to ipak nije trebalo prvi put? To je zato što kad mi nemojte eksplicitno pisati bilo koji konstruktor, kompajler dodaje zadani konstruktor bez argumenata.

Zbog toga smo objekt mogli konstruirati prvi put, iako nismo eksplicitno napisali konstruktor. Zadani konstruktor bez argumenata jednostavno će postaviti sve članove na njihove zadane vrijednosti.

Za predmete, to je null, što je rezultiralo iznimkom koju smo ranije vidjeli.

4. Parametarski konstruktor

Stvarna je korist konstruktora u tome što nam pomažu u održavanju inkapsulacija prilikom ubrizgavanja stanja u objekt.

Dakle, da bismo učinili nešto stvarno korisno s ovim bankovnim računom, moramo biti u mogućnosti ubrizgati neke početne vrijednosti u objekt.

Napraviti to, napišimo a parametarski konstruktor, odnosno konstruktor koji uzima neke argumente:

class BankAccount {public BankAccount () {...} public BankAccount (naziv niza, LocalDateTime otvoren, dvostruko stanje) {this.name = name; this.opened = otvorio; this.balance = ravnoteža; }} 

Sada s našim možemo učiniti nešto korisno Bankovni račun razred:

 LocalDateTime otvorena = LocalDateTime.of (2018, mjesec.JUN, 29, 06, 30, 00); Račun BankAccount = novi BankAccount ("Tom", otvoren, 1000.0f); account.toString (); 

Primijetite, naša klasa sada ima 2 konstruktora. Eksplicitni, bez konstruktora argumenata i parametarski konstruktor.

Možemo stvoriti onoliko konstruktora koliko želimo, ali vjerojatno ne bismo željeli stvoriti previše. Ovo bi bilo malo zbunjujuće.

Ako u našem kodu pronađemo previše konstruktora, nekoliko obrazaca kreativnog dizajna moglo bi biti korisno.

5. Konstruktor kopija

Konstruktori se ne moraju ograničiti samo na inicijalizaciju. Također bi se mogli koristiti za stvaranje ponašanja. Zamislite da trebamo moći stvoriti novi račun od postojećeg.

Novi račun trebao bi imati isto ime kao i stari račun, današnji datum izrade i bez sredstava. To možemo učiniti pomoću a konstruktor kopija:

javni BankAccount (BankAccount ostalo) {this.name = other.name; this.opened = LocalDateTime.now (); this.balance = 0.0f; } 

Sada imamo sljedeće ponašanje:

LocalDateTime otvorena = LocalDateTime.of (2018, mjesec.JUN, 29, 06, 30, 00); Račun BankAccount = novi BankAccount ("Tim", otvoren, 1000.0f); BankAccount newAccount = novi BankAccount (račun); assertThat (account.getName ()). isEqualTo (newAccount.getName ()); assertThat (account.getOpened ()). isNotEqualTo (newAccount.getOpened ()); assertThat (newAccount.getBalance ()). isEqualTo (0.0f); 

6. Lančani konstruktor

Naravno, možda ćemo moći zaključiti neke parametre konstruktora ili daju neke od njih zadane vrijednosti.

Na primjer, mogli bismo samo stvoriti novi bankovni račun samo s imenom.

Pa, kreirajmo konstruktor s a Ime parametar i dajte ostalim parametrima zadane vrijednosti:

javni BankAccount (naziv niza, LocalDateTime otvoren, dvostruko stanje) {this.name = name; this.opened = otvorio; this.balance = ravnoteža; } javni BankAccount (naziv niza) {this (name, LocalDateTime.now (), 0.0f); }

Uz ključnu riječ ovaj, zovemo drugog konstruktora.

Toga se moramo sjetiti ako želimo povezati konstruktor superklase koji moramo koristiti super umjesto ovaj.

Također, upamtite to ovaj ili super izraz uvijek treba biti prva izjava.

7. Vrste vrijednosti

Zanimljiva upotreba konstruktora u Javi je u stvaranju Objekti vrijednosti. Vrijednosni objekt je objekt koji nakon inicijalizacije ne mijenja svoje unutarnje stanje.

Odnosno, objekt je nepromjenjiv. Nepromjenjivost u Javi pomalo je nijansirana i treba biti oprezan prilikom izrade predmeta.

Idemo naprijed i stvorimo nepromjenjivu klasu:

klasa Transakcija {final BankAccount bankAccount; konačni datum LocalDateTime; konačni dvostruki iznos; javna transakcija (račun BankAccount, datum LocalDateTime, dvostruki iznos) {this.bankAccount = account; this.date = datum; this.amount = iznos; }} 

Primijetite, da sada koristimo konačni ključna riječ prilikom definiranja članova razreda. To znači da se svaki od tih članova može inicijalizirati samo unutar konstruktora klase. Ne mogu se kasnije dodijeliti niti jednoj drugoj metodi. Te vrijednosti možemo čitati, ali ih ne mijenjati.

Ako stvorimo više konstruktora za Transakcija klase, svaki će konstruktor trebati inicijalizirati svaku završnu varijablu. Ako to ne učinite, rezultirat će pogreškom u kompilaciji.

8. Zaključak

Obišli smo različite načine na koje konstruktori grade objekte. Kada se koriste razumno, konstrukti čine osnovne gradivne dijelove objektno orijentiranog dizajna u Javi.

Kao i uvijek, uzorci koda mogu se naći na GitHubu.