JAVA PAGRINDAI DETALIAU
Java konstruktorių perkrovimas
Konstruktorių perkrovimas leidžia tai pačiai klasei turėti kelis konstruktorius su skirtingais parametrų sąrašais. Todėl objektą galima sukurti pateikiant tik tuo metu žinomus duomenis.
Kam reikia kelių konstruktorių?
Įsivaizduok siuntų registravimo programą. Kartais dar nežinome nieko, kartais žinome tik gavėją, o kartais turime visus siuntos duomenis. Vietoje trijų skirtingų klasių galime pateikti tris tos pačios klasės sukūrimo būdus.
class Siunta {
String gavejas;
double svoris;
boolean skubi;
Siunta() {
gavejas = "Nenurodytas";
svoris = 0.0;
skubi = false;
}
Siunta(String gavejas) {
this.gavejas = gavejas;
svoris = 0.0;
skubi = false;
}
Siunta(String gavejas, double svoris, boolean skubi) {
this.gavejas = gavejas;
this.svoris = svoris;
this.skubi = skubi;
}
void rodyti() {
System.out.println(gavejas + ", " + svoris + " kg, skubi: " + skubi);
}
}
Siunta neuzpildyta = new Siunta();
Siunta laiskas = new Siunta("Ieva");
Siunta deze = new Siunta("Mantas", 4.5, true);
neuzpildyta.rodyti();
laiskas.rodyti();
deze.rodyti();Nenurodytas, 0.0 kg, skubi: false
Ieva, 0.0 kg, skubi: false
Mantas, 4.5 kg, skubi: true
new Siunta()neturi argumentų, todėl Java pasirenka konstruktorių be parametrų.new Siunta("Ieva")turi vienąStringargumentą, todėl pasirenkamas antras konstruktorius.- Trečiame iškvietime perduodami
String,doubleirboolean, todėl tinka trečias konstruktorius. - Pasirinkimas atliekamas kompiliavimo metu pagal argumentų skaičių, tipus ir jų tvarką.
Kuo konstruktoriai turi skirtis?
class Bilietas {
Bilietas(String renginys) { }
Bilietas(String renginys, int vieta) { }
Bilietas(int vieta, String renginys) { }
}Kodas tik aprašo tris leidžiamus Bilietas objektų kūrimo būdus.
Konstruktoriaus parašą lemia parametrų:
- skaičius;
- tipai;
- tipų tvarka.
Parametrų pavadinimai parašo nekeičia. Taip pat konstruktorius neturi grąžinamojo tipo, todėl juo konstruktorių atskirti negalima.
Bendrą darbą perduok su this(...)
Pirmajame pavyzdyje kai kurios pradinės reikšmės kartojosi. Patogiau turėti vieną pagrindinį konstruktorių, o trumpesnius konstruktorius nukreipti į jį:
class Puodelis {
String spalva;
int talpaMl;
Puodelis() {
this("baltas", 300);
}
Puodelis(String spalva) {
this(spalva, 300);
}
Puodelis(String spalva, int talpaMl) {
this.spalva = spalva;
this.talpaMl = talpaMl;
}
}
Puodelis pirmas = new Puodelis();
Puodelis antras = new Puodelis("mėlynas");
System.out.println(pirmas.spalva + " " + pirmas.talpaMl);
System.out.println(antras.spalva + " " + antras.talpaMl);baltas 300
mėlynas 300
- Konstruktorius be parametrų pasirenka numatytąją spalvą ir talpą.
- Konstruktorius su spalva perduoda ją pagrindiniam konstruktoriui, o talpai naudoja
300. - Pagrindinis dviejų parametrų konstruktorius vienoje vietoje priskiria abu atributus.
this(...)privalo būti pati pirmoji konstruktoriaus instrukcija.
Parašius konstruktorių, automatinis tuščias konstruktorius dingsta
class Knyga {
String pavadinimas;
Knyga(String pavadinimas) {
this.pavadinimas = pavadinimas;
}
}
Knyga pirma = new Knyga("Altorių šešėly");
// Knyga antra = new Knyga(); // Kompiliavimo klaidaPirmas objekto sukūrimas veikia. Atkomentavus antrą eilutę, kodas nesikompiliuos, nes klasė neturi konstruktoriaus be parametrų.
Java automatiškai suteikia tuščią konstruktorių tik tada, kai klasėje patys neaprašėme nė vieno konstruktoriaus. Jei norime ir tuščio, ir parametrizuoto varianto, turime aiškiai parašyti abu.
Parametrų pavadinimų pakeisti nepakanka
class Saskaita {
Saskaita(String savininkas, int numeris) { }
// Klaida: toks pats konstruktoriaus parašas
Saskaita(String vardas, int kodas) { }
}Kodas nesukompiliuojamas, nes abu konstruktoriai turi tą patį parašą: Saskaita(String, int).
Java žiūri į parametrų tipus ir jų tvarką, o ne į vardus savininkas, vardas, numeris ar kodas.
Venk dviprasmiško iškvietimo
class Pranesimas {
Pranesimas(String tekstas) { }
Pranesimas(StringBuilder tekstas) { }
}
// Klaida: null tinka abiem konstruktoriams
Pranesimas pranesimas = new Pranesimas(null);Kodas nesukompiliuojamas: null gali tikti ir String, ir StringBuilder, todėl kompiliatorius negali vienareikšmiškai pasirinkti.
Perkrovimai turi būti patogūs žmogui ir aiškūs kompiliatoriui. Jei iškvietimai lengvai supainiojami, prasmingiau naudoti aiškiai pavadintus kūrimo metodus arba kitokią klasės struktūrą.
Konstruktorių ir metodų perkrovimas
| Savybė | Konstruktoriai | Metodai |
|---|---|---|
| Paskirtis | Paruošti naują objektą | Atlikti veiksmą |
| Pavadinimas | Visada sutampa su klasės pavadinimu | Gali būti bet koks tinkamas metodo vardas |
| Grąžinamasis tipas | Nerašomas | Privalomas, įskaitant void |
| Iškvietimas | Kuriant objektą su new arba per this(...) | Rašant metodo pavadinimą ir argumentus |
| Pasirinkimas | Kompiliavimo metu pagal argumentus ir galimus parašus | |
Ką verta prisiminti?
- Perkrauti konstruktoriai suteikia kelis tos pačios klasės objekto sukūrimo būdus.
- Jie privalo skirtis parametrų skaičiumi, tipais arba tipų tvarka.
- Kompiliatorius konstruktorių pasirenka pagal perduotus argumentus.
this(...)padeda išvengti pasikartojančios inicializavimo logikos.this(...)turi būti pirmoji konstruktoriaus instrukcija, o cikliniai konstruktorių iškvietimai neleidžiami.- Aprašius bent vieną konstruktorių, Java nebesukuria automatinio konstruktoriaus be parametrų.

