Contacte

constructori Java. De ce sunt necesari constructori? Conceptul de constructor implicit

1. Conceptul de constructor implicit

Un constructor implicit este un constructor care nu acceptă parametri. Un constructor implicit poate fi declarat explicit într-o clasă sau generat automat.

În cel mai general caz, pentru clasa ClassName, constructorul implicit arată astfel:

clasă Numele clasei(... // declarația constructorului Numele clasei() ( // corpul constructorului // ... } ... }
2. În ce cazuri este generat automat constructorul implicit în clasă și în care nu? Exemplu

Dacă nu este declarat niciun constructor în clasă, atunci va fi generat un constructor implicit. Adică, un constructor implicit este generat automat într-o clasă numai dacă clasa nu conține implementări ale altor constructori. Dacă o clasă conține o implementare a cel puțin unui constructor cu parametri, atunci pentru a declara un constructor implicit, acesta trebuie declarat explicit în clasă.

De exemplu.În următoarea declarație de clasă, un constructor implicit este generat automat

clasă CMyClass( int d; int GetD() ( întoarcere d; ) gol SetD( int nd) ( d = nd; ) )

Codul de mai sus înseamnă că puteți declara un obiect de clasă folosind constructorul implicit:

// funcționează deoarece clasa nu mai implementează niciun constructor CMyClass mc = nou CMyClass();

Dacă cel puțin un alt constructor este adăugat în corpul clasei CMyClass (de exemplu, un constructor cu un parametru), atunci constructorul implicit nu va fi generat automat

clasă CMyClass( int d; // constructorul implicit nu mai este generat automat CMyClass( int nd) ( d = nd; ) int GetD() ( întoarcere d; ) gol A stabilit( int nd) ( d = nd; ) )

După implementarea de mai sus, declararea unui obiect folosind un constructor implicit va eșua. Cu toate acestea, este posibil să declarați un obiect folosind un constructor cu un singur parametru

// eroare de compilare deoarece un alt constructor este deja declarat în clasă // CMyClass mc = new CMyClass(); CMyClass mc2= nou CMyClass(7); // și acest cod funcționează

Linia de mai sus va avea ca rezultat o eroare de compilare:

Constructorul CMyClass() este nedefinit

Pentru a avea o implementare implicită a constructorului și pentru a declara un obiect de clasă folosind un constructor implicit, acesta trebuie să fie setat în mod explicit. Ar putea fi, de exemplu, după cum urmează

clasă CMyClass( int d; // declarație explicită implicită a constructorului CMyClass() ( d = 0; ) // declarație constructor cu 1 parametru, CMyClass( int nd) ( d = nd; ) int GetD() ( întoarcere d; ) gol A stabilit( int nd) ( d = nd; ) )

După o astfel de implementare, puteți crea o instanță a clasei folosind doi constructori, de exemplu

CMyClass mc = nou CMyClass(); // constructorul implicit este apelat mc.d = 25; CMyClass mc2= nou CMyClass(5); // este apelat constructorul cu 1 parametru

3. Apelarea constructorilor de la alți constructori. Exemplu

Limbajul de programare Java vă permite să apelați constructori de clasă de la un alt constructor din aceeași clasă. Pentru aceasta, este folosit cuvântul cheie this, care este o referință la clasa curentă.

Exemplu. Exemplul demonstrează utilizarea clasei CPixel, care implementează un pixel pe un ecran de monitor.

// Clasa care implementează un pixel pe ecranul monitorului public clasă CPixel( // variabilele clasei interne privat int X y; // coordonatele pixelilor privat int culoare; // culoarea pixelilor // constructor fără parametri (constructor implicit) CPixel() ( x = y = culoare = 0; ) // constructor cu 2 parametri care inițializează doar coordonatele CPixel( int _X, int _y) ( x = _x; y = _y; culoare = 0; ) // constructor cu 1 parametru care inițializează doar culoarea CPixel( int _culoare) (culoare = _culoare; x = y = 0; ) // Constructor cu 3 parametri care apelează constructorul cu 2 parametri CPixel( int _X, int _e, int _culoare) ( // apel constructor cu 2 parametri: prima operație obligatorie și o singură dată acest(_X y); //this(_culoare); // apelul repetat al constructorului este interzis acest.culoare = _culoare; // deci este posibil ) // metode de acces int GetX() ( întoarcere X; ) int GetY() ( întoarcere y; ) int GetColor() ( întoarcere culoare; ) )

Utilizarea clasei CPixel într-un alt cod de program (metodă)

CPixel cp1= nou CPixel(2,8); // apel constructor cu 2 parametri CPixel cp2= nou CPixel(3,5,8); // apelează un constructor care va apela un alt constructor int d; d = cp1.GetX(); // d = 2 d = cp2.GetColor(); // d = 8 d = cp2.GetY(); // d = 5 ...

4. Ce restricții (cerințe) sunt impuse la apelarea altor constructori dintr-un constructor de clasă?

Pentru a apela corect alți constructori dintr-un constructor de clasă, trebuie respectate următoarele cerințe (restricții):

  • numai un alt constructor de clasă poate fi apelat. Apelarea a doi sau mai mulți constructori ai acestei clase este interzisă. Aceasta rezultă din logica că un constructor de clasă este proiectat să creeze un obiect de clasă o singură dată (și nu de două ori sau de mai multe);
  • apelarea unui alt constructor trebuie să fie prima operație din constructorul apelant. Dacă în constructorul apelant apelul altui constructor este implementat prin a doua (a treia, etc.) operație, compilatorul va genera o eroare.

Metoda în Java este un set de expresii, a căror totalitate vă permite să efectuați o anumită operație. Deci, de exemplu, când este apelată metoda System.out.println(), sistemul execută o serie de comenzi pentru a imprima un mesaj pe consolă.

În acest pas, veți învăța cum să vă creați propriile metode cu sau fără valori returnate, să apelați metode cu sau fără parametri și să izolați metodele atunci când dezvoltați un program.

Creați o metodă

Mai jos este un exemplu care ilustrează sintaxa unei metode, cum să creați o metodă în Java.

Sintaxă

public static int methodName(int a, int b) ( // corp )
  • public static - modificator;
  • int - tipul de returnare;
  • methodName - numele metodei;
  • a, b - parametri formali;
  • int a, int b - lista de parametri.

Definiția unei metode este reprezentată de antetul și corpul metodei. Același lucru îl putem observa în următoarea sintaxă de creare a metodei.

Sintaxă

modificator returnType nameOfMethod (Lista de parametri) ( // corpul metodei )

Sintaxa de mai sus include:

  • modificator - determină tipul de acces pentru metodă și posibilitatea utilizării acesteia.
  • returnType - metoda poate returna o valoare.
  • nameOfMethod - Specifică numele metodei. Semnătura unei metode include numele metodei și o listă de parametri.
  • Lista parametrilor - lista parametrilor este reprezentată de tipul, ordinea și numărul parametrilor metodei. Această opțiune este setată în mod arbitrar; un parametru nul poate fi prezent în metodă.
  • corpul metodei - corpul metodei definește metoda de lucru cu comenzi.

Exemplu

/* fragmentul de cod returnează minimul dintre două numere */ public static int minFunction(int n1, int n2) ( int min; dacă (n1 > n2) min = n2; altfel min = n1; return min; )

Apel de metodă

Înainte de a utiliza o metodă, aceasta trebuie apelată. Există două moduri de a apela o metodă în Java, de exemplu. metoda produce o valoare returnată sau nu produce (nu există valoare returnată).

Algoritmul de apelare a metodei este destul de simplu. Când un program apelează o metodă în Java, controlul programatic este transferat metodei apelate. Această metodă apelată returnează apoi controlul clientului apelant în două cazuri, dacă:

  • se execută o instrucțiune return;
  • s-a ajuns la acolada de închidere a sfârșitului metodei.

Metoda void return invocă comanda. Luați în considerare un exemplu:

System.out.!");

Metoda returnării valorii poate fi ilustrată cu următorul exemplu:

int rezultat = sum(6, 9);

Exemplul de mai jos demonstrează cum să definiți și să apelați o metodă în Java.

Exemplu

clasă publică ExampleMinNumber ( public static void main(String args) ( int a = 11; int b = 6; int c = minFunction(a, b); System.out.println("Min value = " + c); ) / * Returnează minimum de două numere */ public static int minFunction(int n1, int n2) ( int min; if (n1 >

Valoarea minimă = 6

Cuvântul cheie void

Cuvântul cheie voidîn Java ne permite să creăm metode care nu returnează o valoare. În exemplul de mai jos, am luat în considerare o metodă de tip void - methodRankPoints. Metodele Java void nu returnează nicio valoare. Apelarea unei metode de tip void este efectuată printr-o comandă, de exemplu. methodRankPoints(255.7);. Aceasta este o expresie java care se termină cu punct și virgulă, așa cum se arată în exemplul de mai jos:

Exemplu

clasă publică ExampleVoid ( public static void main(String args) ( methodRankPoints(255.7); ) public static void methodRankPoints(puncte duble) ( dacă (puncte >= 202.5) ( System.out.println("Rank A1"); )altfel if (puncte >= 122,4) ( System.out.println ("Rang A2"); )else ( System.out.println ("Rang A3"); ) ) )

Ca urmare, se va obține următorul rezultat:

Rangul A1

Transmiterea parametrilor după valoare în Java

Când se execută procesul de apelare, Java transmite argumente. Procedura trebuie efectuată în ordinea specificată de parametrii corespunzători din specificația metodei. Parametrii pot fi transferați prin valoare sau prin referință.

În Java, trecerea parametrilor după valoare înseamnă apelarea unei metode cu un parametru. Din acest motiv, valoarea argumentului este transmisă parametrului.

Exemplu

Următorul program arată un exemplu de transmitere a unui parametru după valoare. Valorile argumentului rămân neschimbate chiar și după apelarea metodei.

Exemplu de schimbare a claselor publice ( public static void main(String args) ( int a = 30; int b = 45; System.out.println ("Înainte de a trece, valorile argumentelor a = " + a + " și b = " + b ); // Apelarea metodei de transfer swapFunction(a, b); System.out.println("\nAcum, înainte și după transmiterea valorii argumentelor "); System.out.println("a rămas neschimbată, a = " + a + " și b = " + b); ) public static void swapFunction(int a, int b) ( System. out. println ("Înainte de schimbare: a = " + a + " b = " + b) ); // Transmiterea parametrilor int c = a; a = b; b = c; System.out.println ("După înlocuire: a = " + a + " b = " + b); ) )

Obtinem urmatorul rezultat:

Înainte de a trece, valorile argumentelor a = 30 și b = 45 Înainte de înlocuire: a = 30 b = 45 După înlocuire: a = 45 b = 30 Acum, înainte și după transmitere, valorile argumentele au rămas neschimbate, a = 30 și b = 45

Supraîncărcarea metodei

Supraîncărcarea metodei în Java- cazul în care în clasă există două sau mai multe metode cu același nume, dar parametri diferiți. Acest proces este diferit de metodele de suprascriere. Când metodele sunt suprascrise, metoda este caracterizată de același nume, tip, număr de parametri și așa mai departe.

Luați în considerare exemplul care a fost prezentat mai sus când definiți numerele minime ale unui tip întreg. Deci, să presupunem că vrem să definim numărul minim al unui tip dublu. În acest caz, conceptul de supraîncărcare va fi introdus pentru a crea două sau mai multe metode cu același nume, dar cu parametri diferiți.

Exemplul de mai sus ilustrează cele de mai sus.

Exemplu

clasă publică ExempluSupraîncărcare ( public static void main(String args) ( int a = 7; int b = 3; double c = 5.1; double d = 7.2; int result1 = minFunction(a, b); // aceeași funcție cu alți parametri rezultat dublu2 = minFunction(c, d); System.out.println ("Valoare minimă = " + rezultat1); System.out.println ("Valoare minimă = " + rezultat2); ) // pentru întreg public static int minFunction ( int n1, int n2) ( int min; dacă (n1 > n2) min = n2; else min = n1; return min; ) // pentru dublu public static dublu minFunction(dublu n1, dublu n2) ( dublu min; dacă ( n1 > n2) min = n2; altfel min = n1; întoarcere min; ) )

Ca urmare, se va obține următorul rezultat:

Valoare minimă = 3 Valoare minimă = 5,1

Metodele de supraîncărcare fac un program lizibil. Deci există două metode cu același nume, dar cu parametri diferiți. Ca rezultat, am obținut numărul minim int și numărul de tip dublu.

Utilizarea argumentelor din linia de comandă

În timpul programului, poate fi necesar să transferați anumite informații. Acest lucru se poate face în Java prin transmiterea argumentelor liniei de comandă către main().

În Java, un argument de linie de comandă reprezintă informația care urmează imediat numele unui program pe linia de comandă atunci când este executat. Obținerea accesului la argumentele liniei de comandă într-un program java nu este dificilă. Ele sunt stocate ca șir în matricea de șiruri transmisă la main().

Exemplu

Programul de mai jos afișează toate argumentele liniei de comandă invocate.

Clasa publică CommandLine ( public static void main(String args) ( for(int i = 0; i

Încercați să rulați acest program așa cum se arată mai jos:

$java CommandLine este linia de comandă 300 -200

Ca urmare, se va obține următorul rezultat:

args: acesta este args: linia de comandă args: șir args: 300 args: -200

Constructor în Java

În Java constructor inițializează un obiect când este creat. Numele său este similar cu numele clasei, iar sintaxa sa este similară cu cea a unei metode. Cu toate acestea, spre deosebire de acesta din urmă, constructorul nu are o valoare returnată.

De obicei, un constructor în Java poate fi folosit pentru a seta o valoare inițială variabilelor de instanță definite de o clasă sau pentru a efectua orice alte proceduri de pornire necesare pentru a crea un obiect complet format.

Constructorii sunt prezenți în toate clasele, indiferent de modul în care sunt specificati, deoarece Java furnizează automat un constructor implicit care inițializează toate variabilele membrilor clasei la zero. Cu toate acestea, odată ce vă definiți propriul constructor, constructorul implicit nu va mai fi folosit.

Exemplu

Exemplul de mai jos arată utilizarea unui constructor de clasă fără parametri.

// Constructor simplu. clasa MyClass ( int x; // Urmează constructorul MyClass() ( x = 10; ) )

Pentru a inițializa obiecte, trebuie să faceți un apel de constructor ca în exemplul următor.

Clasa publică ConsDemo ( public static void main(String args) ( MyClass t1 = new MyClass(); MyClass t2 = new MyClass(); System.out.println(t1.x + " " + t2.x); ) )

Obtinem rezultatul:

Constructor parametrizat

Cel mai adesea, veți avea nevoie de un constructor care preia unul sau mai mulți parametri. Adăugarea de parametri la un constructor este la fel cu adăugarea lor la o metodă, trebuie doar să-i puneți în paranteze după numele constructorului.

Exemplu

// Constructor simplu. clasa MyClass ( int x; // Sub constructorul MyClass(int i) ( x = i; ) )

Pentru a inițializa obiectele, va trebui să apelați constructorul ca în exemplul următor.

Clasa publică ConsDemo ( public static void main(String args) ( MyClass t1 = new MyClass(10); MyClass t2 = new MyClass(20); System.out.println(t1.x + " " + t2.x); ) )

Obtinem urmatorul rezultat:

cuvânt cheie asta

cuvânt cheie asta- este folosit pentru a se referi la clasa curentă având în vedere o metodă sau un constructor de instanță. Folosind aceasta în Java, vă puteți referi la instanțe de clasă, cum ar fi constructori, variabile și metode.

Notă: cuvântul cheie this este folosit numai în cadrul metodelor sau constructorilor de instanță.

De obicei, acest cuvânt cheie în Java este folosit pentru:

  • diferențierea dintre variabilele de instanță și variabilele locale dacă au același nume, ca parte a unui constructor sau a unei metode.
clasă Student (înt age; Student (int age) (această vârstă = vârstă;))
  • apelarea unui constructor de un tip (constructor parametrizat sau constructor implicit) din altul dintr-o clasă. Acest proces este numit și invocare explicită a constructorului.
clasa Student (înt age Student() ( this(20); ) Student(int age) ( this.age = age; ) )

Exemplu

Clasa publică This_Example ( // Inițializați variabila num int num = 11; This_Example() ( System. out. println("Acesta este un exemplu de program cu cuvântul cheie this"); ) This_Example(int num) ( // Apelați valoarea implicită constructor this(); // Atribuiți variabilei locale num variabilei de instanță num this.num = num; ) public void greet() ( System.out.println("Bună! Bun venit la ProgLang!"); ) public void print() ( // Variabila locală num int num = 20 // Apelați metoda clasei greet this.greet() // Imprimați variabila locală System.out.println("Valoarea variabilei locale num: " + num); // Imprimați variabila de instanță System. .out.println("Valoarea variabilei de instanță num: " + this.num); ) public static void main(String args) ( // Inițializați acest_exemplu clasa obj1 = new This_Example(); // Apelați metoda de imprimare obj1.print() ; // Trecerea noii valori a variabilei num prin constructorul parametrizat This_Example obj2 = new This_Example(30); // Tu apelarea metodei print din nou obj2.print(); ) )

Ca urmare, se va obține următorul rezultat:

Acesta este un exemplu de program cu acest cuvânt cheie Bună ziua! Bun venit la Proglang! Valoarea variabilei locale num: 22 Valoarea variabilei de instanță num: 11 Acesta este un exemplu de program cu cuvântul cheie this Hello! Bun venit la Proglang! Valoarea variabilei locale num: 22 Valoarea variabilei de instanță num: 30

Argumente variabile (var-args)

JDK 1.5 și o versiune ulterioară vă permite să transmiteți un număr variabil de argumente de același tip unei metode. Un parametru dintr-o metodă este declarat astfel:

TypeName... parameterName

Când declarați o metodă, specificați tipul urmat de puncte suspensive (...). Într-o metodă poate fi specificat un singur parametru de lungime variabilă, iar acest parametru trebuie să fie ultimul parametru. Orice parametri obișnuiți trebuie să îl precedă.

Exemplu

public class VarargsDemo ( public static void main(String args) ( // Apel la metoda cu variabila args printMax(27, 11, 11, 5, 77.1); printMax(new double(10, 11, 12, 77, 71)); ) public static void printMax(duble... numere) ( if (numbers.length == 0) ( System.out.println("Nu a fost trecut niciun argument"); return; ) dublu rezultat = numere; for (int i = 1 ; rezultat i) rezultat = numere[i]; System.out.println ("Valoare maximă " + rezultat); ) )

Ca urmare, se va obține următorul rezultat:

Valoarea maximă 77,1 Valoare maximă 77,0

metoda finalize().

metoda finalize().- o metodă care va fi apelată imediat înainte de distrugerea finală a obiectului de către colectorul de gunoi. (finalizator). În Java, finalize() poate fi folosit pentru a asigura finalizarea curată a unui obiect.

De exemplu, putem folosi finalize() pentru a ne asigura că un fișier deschis deținut de un anumit obiect a fost închis.

Pentru a adăuga un finalizator la o clasă, trebuie pur și simplu să definiți o metodă finalize() în Java. Mediul de rulare Java apelează această metodă chiar înainte de procesarea unui obiect din această clasă.

Ca parte a metodei finalize(), specificați acțiunile care trebuie efectuate înainte ca obiectul să fie distrus.

În general, metoda finalize() arată astfel:

Protected void finalize() ( // finalizarea codului aici )

Aici, cuvântul cheie protejat reprezintă un specificator care împiedică accesarea finalize() de către codul definit în afara clasei sale.

Acest lucru indică faptul că nu puteți ști cum sau chiar când va fi executat finalize(). De exemplu, dacă programul dumneavoastră se termină înainte de colectarea gunoiului, finalize() nu va fi executat.

Un constructor este o metodă specială care este apelată atunci când este creat un nou obiect. Nu este întotdeauna convenabil să inițializați toate variabilele de clasă atunci când creați o instanță a acesteia. Uneori este mai ușor să aveți unele valori create implicit atunci când obiectul este creat. De fapt, constructorul este necesar pentru inițializarea automată a variabilelor.

Un constructor inițializează un obiect direct în momentul creării. Numele constructorului este același cu numele clasei, inclusiv majuscule, iar sintaxa unui constructor este similară cu cea a unei metode fără valoare returnată.

Private int Cat(); // așa arată metoda numită Cat Cat(); // așa arată constructorul clasei Cat

Spre deosebire de o metodă, un constructor nu returnează niciodată nimic.

Un constructor definește acțiunile care trebuie întreprinse atunci când un obiect al unei clase este creat și este o parte importantă a unei clase. De regulă, programatorii încearcă să specifice în mod explicit un constructor. Dacă nu există un constructor explicit, atunci Java va crea automat unul pentru utilizare implicită. Când am implementat clasa cutie, atunci nu a fost creat niciun constructor.

Să adăugăm un constructor la clasă care va seta pur și simplu valorile inițiale pentru casetă.

Class Box ( int lățime; // lățime casetă int înălțime; // înălțime casetă int adâncime; // adâncime casetă // Constructor Box() ( lățime = 10; înălțime = 10; adâncime = 10; ) // calculează volumul casetei int getVolume() ( lățime de întoarcere * înălțime * adâncime; ) )

Am eliminat temporar metoda setDim()și a adăugat un constructor. Să vedem ce se întâmplă:

Box catBox = new Box(); mInfoTextView.setText("Volum casetei: " + catBox.getVolume());

Programul va scoate volumul cutiei, chiar dacă nu am specificat nicio dimensiune pentru el. Datorită constructorului, orice cutie creată va avea un volum fix.

Desigur, puteți returna o metodă setDim()(vezi articolul despre cursuri) și setează-ți propriile dimensiuni pentru cutie:

Box catBox = new Box(); // setează dimensiuni personalizate pentru caseta catBox. setDim(10, 20, 30); mInfoTextView.setText("Volum casetei: " + catBox.getVolume());

Până acum ar trebui să vă fie clar că atunci când după cuvântul cheie nou scriem numele clasei cu paranteze, apoi numim de fapt constructorul clasei.

Apare întrebarea - dar la început, la crearea clasei, nu am creat un constructor, totuși, codul newBox() a lucrat. Faptul este că, dacă constructorul nu este definit în mod explicit, atunci Java va crea un constructor care va fi folosit implicit. În acest caz, va atribui pur și simplu valori zero tuturor variabilelor. Dacă ați creat singur un constructor, atunci constructorul implicit nu va fi folosit.

Ca orice metodă, un constructor poate avea argumente. Argumentele constructorului transmit parametri pentru a inițializa obiectul. De exemplu, dacă clasa pisică exista un constructor care ia ca argument un intreg care denota varsta pisicii, apoi obiectele pisică va fi creat astfel:

Cat cat = noua Pisica(8); // pisica are 8 ani

În cazul în care un cat(int) este singurul constructor de clasă, compilatorul nu va permite crearea de obiecte pisicăîntr-un alt fel.

Dar să revenim la cutiile pentru pisici. Constructorul creat de noi nu este deosebit de util, deoarece creează aceleași casete. Să creăm un constructor cu parametri în clasă cutieși comentați primul constructor fără parametri:

// Al doilea constructor Casetă (int ​​w, int h, int d) ( lățime = l; înălțime = h; adâncime = d; )

Dacă clasa conține un constructor cu parametri, atunci va trebui să specificați valorile atunci când declarați clasa:

// Acest constructor nu mai este valid // Box catBox = new Box(); // În constructor, trebuie să specificați valorile dimensiunii casetei Box catBox = new Box(100, 200, 100); mInfoTextView.setText("Volum casetei: " + catBox.getVolume());

Apropo, cu un astfel de constructor, metoda setDim() nu mai avem nevoie. Putem seta dimensiunile cutiei direct în constructor. Deoarece cutia este cel mai probabil constantă și nu își schimbă dimensiunea, metoda este probabil de prisos. Dar dacă schimbăm dimensiunea cutiei, atunci metoda va trebui lăsată.

O clasă poate avea mai mulți constructori. Decomentați primul constructor și creați două casete - o casetă implicită și o casetă mare.

Caseta defaultBox = new Box(); mInfoTextView.setText("Volum cutie standard: " + defaultBox.getVolume()); Box bigBox = casetă nouă (100, 200, 200); mInfoTextView.append("\nVolum casete mari: " + bigBox.getVolume());

Adică, vedem că constructorii acceptă supraîncărcarea, la fel ca și metodele.

De exemplu, putem crea un alt constructor special pentru o cutie sub forma unui cub, unde toate laturile sunt egale:

// Al treilea constructor pentru cubul Box(int ​​​​len) ( lățime = înălțime = adâncime = len; )

Calculați dimensiunea cubului:

Box cub = new Box(5); intvol = cub.getVolume(); mInfoTextView.setText("Volum cub: " + vol);

Utilizarea unui obiect ca parametri

Până acum am folosit tipuri simple ca parametri în constructori. Dar puteți trece și un obiect al clasei în sine. Să adăugăm un alt constructor:

// Folosește un obiect de tip Box Box(Box ob) ( lățime = ob.width; height = ob.height; depth = ob.depth; )

În codul programului, puteți utiliza constructorul după cum urmează:

Caseta1 = casetă nouă (100, 200, 100); Box cloneBox = new Box(box1); intvol = cloneBox.getVolume(); mInfoTextView.setText("Volum casetei: " + vol);

Clasa cutie (sursa)

pachet en.alexanderklimov.box; class Box ( int lățime; // lățime a casetei int înălțime; // înălțime a casetei int adâncime; // adâncime a casetei // Constructor Box() ( lățime = 10; înălțime = 10; adâncime = 10; ) // Al doilea constructor Box( int w, int h, int d) ( lățime = l; înălțime = h; adâncime = d; ) // Al treilea constructor pentru cubul Box(int ​​​​len) ( lățime = înălțime = adâncime = len; ) // Folosește un obiect de tip Box Box(Box ob) ( lățime = ob.width; height = ob.height; depth = ob.depth; ) // calculează volumul casetei int getVolume() ( return width * height * adâncime; ) // setați dimensiunile casetei void setDim (int w, int h, int d) ( lățime = l; înălțime = h; adâncime = d; ) )

Apelarea constructorilor supraîncărcați prin this()

Când aveți de-a face cu constructori supraîncărcați, este convenabil să apelați un constructor de la altul prin cuvântul cheie acest. La executarea constructorului acest() constructorul supraîncărcat care se potrivește cu lista de parametri este executat mai întâi. Apoi, instrucțiunile din interiorul constructorului original, dacă există, sunt executate. Apelul constructorului acest() trebuie să fie prima instrucțiune din constructor.

Mai întâi, să creăm o clasă care nu folosește un constructor. acest() pentru a înțelege diferența.

Clasa Cat ( int varsta; int ziua de nastere; // Initializeaza variabilele in mod explicit Cat(int i, int j) ( varsta = i; ziua de nastere = j; ) // Initializeaza variabilele cu aceeasi valoare Cat(int i) ( varsta = i; ziua de naștere = i; ) // Setați valorile implicite la 0 Cat() ( vârsta = 0; ziua de naștere = 0; ) )

Am creat o clasă cu trei constructori. Rescrieți clasa folosind constructorul acest().

Clasa Cat( int varsta; int ziua de nastere; // Initializeaza variabilele in mod explicit Cat(int i, int j) ( varsta = i; ziua de nastere = j; ) // Initializeaza variabilele cu aceeasi valoare Cat(int i) ( this(i, i); // apelând Cat(i, i); ) // Setați valorile implicite la 0 Cat() ( this(0); // apelând Cat(0); ) )

Acum avem un singur constructor care atribuie valori câmpurilor - Cat(int, int). Ce se întâmplă atunci când instrucțiunea este executată:

Cat cat = noua Pisica(8);

Apelul constructorului pisica(8) determină executarea constructorului aceasta (8, 8), ceea ce este echivalent cu apelarea constructorului Pisica (8, 8).

Ce se întâmplă atunci când instrucțiunea este executată:

Cat cat2 = nou Cat();

În acest caz, constructorul este apelat aceasta(0), care determină executarea constructorului pisica(0), deoarece aceasta este versiunea constructorului care se potrivește cu lista de parametri. În același timp, constructorul pisica(0) cheamă în esență constructorul Pisica(0, 0).

Utilizarea constructorilor supraîncărcați printr-un constructor acest() vă permite să eliminați duplicarea codului, reducând timpul de încărcare a clasei.

Dar fii atent, pentru că constructorii care apelează la un constructor acest(), sunt puțin mai lente.

constructor privat

Uneori, o clasă este creată doar pentru a stoca unele câmpuri statice și metode statice. Este obișnuit ca astfel de clase să fie numite utilitati, dar acest lucru este opțional. O astfel de clasă nu are nevoie de un constructor, dar dacă autorul clasei nu a creat unul, atunci sistemul însuși va crea un constructor implicit. Un astfel de constructor nu are sens și poate fi și o sursă de erori. Pentru a vă proteja de această problemă, trebuie să creați în mod explicit un constructor gol și să îl faceți privat.

Public class Utils ( private Utils() ( throw new AssertionError(); ) ... //codul dvs. corect // Cod incorect, doar pentru scopuri demonstrative! public static void someMethod()( Utils utils = new Utils(); utils .toString(); ))

Linia aruncați o nouă AssertionError() nu este necesar, dar va ajuta la identificarea erorii dacă apelați constructorul din clasa în sine. Compilatorul va omite această opțiune, dar programul se va închide cu o eroare.

Utils.someMethod(); // programul se va închide cu o eroare

Nu puteți crea o subclasă pentru această clasă.

Adevărul este că:

1. Dacă creați o clasă și definiți un constructor cu argumente în ea (clasa AClass, care are un singur constructor care ia int i), atunci compilatorul nu va mai crea un constructor implicit. Pentru că asta ar rupe contractul AClass, care nu poate fi inițializat fără argumente. Dacă doriți să aveți și un constructor implicit, setați-l în mod explicit acum.

În caz contrar, ar fi imposibil să previi crearea unui constructor implicit, ceea ce ar fi rău.

2. Când se creează constructori ai unei clase BClass care este moștenit de la o altă clasă, compilatorul cere ca prima linie a constructorului să fie un apel către un alt constructor (moștenit sau din această clasă).

De ce? Pentru că, din moment ce derivați dintr-o clasă, doriți să reutilizați logica acesteia. Constructorul aduce o instanță a clasei la o stare integrală inițială. În cazul dumneavoastră, AClass necesită un argument pentru inițializare, fără de care JVM-ul nu știe cum să inițializeze o instanță a clasei.

Dacă clasa nu are constructori definiți, atunci încearcă să creeze un constructor implicit, de exemplu. fara argumente:

clasa publică ACclass1 ( )

Deoarece niciun constructor nu este definit în mod explicit aici ȘI clasa nu este moștenită de la alte clase, compilatorul generează un constructor implicit.

Aceasta este echivalentă cu această definiție:

Clasa publică AClass1 ( public AClass1() ( ) )

Acum să ne uităm la BClass1:

clasa publică BClass1 extinde AClass1 ( )

Nici aici constructorii nu sunt definiți în mod explicit, iar compilatorul încearcă să creeze un constructor implicit. Deoarece clasa AClass1 are un constructor implicit, va crea un constructor implicit care va apela constructorul lui AClass1. Acest cod este echivalent cu acesta:

Clasa publică BClass1 extinde AClass1 ( public BClass1() ( super(); ) )

În cazul dvs., o clasă este creată FĂRĂ un constructor implicit:

Public AClass ( public AClass(int i) ( ) )

Deoarece (cel puțin un) constructor este declarat aici, constructorul implicit nu mai este creat. Adică, un astfel de cod nu va mai compila:

AClass a = nou AClass(); // nu funcționează

nevoie de ceva de genul

AClass a = nou ACclass(1);

În consecință, orice constructor BClass va necesita un apel către un constructor AClass sau BClass. Cu această descriere, compilatorul va jura:

Public BClass extinde AClass()

Deoarece va exista o încercare de a apela constructorul implicit al clasei AClass, care nu este definit:

Public BClass extinde AClass ( public BClass() ( super(); // eroare; nu există un astfel de constructor în AClass ) )

Cu toate acestea, este posibil să creați un BClass cu un constructor implicit setând constructorul AClass la o anumită valoare:

Clasa publică BClass extinde AClass ( public BClass() ( super(1); ) )

Aceasta se va compila.

Salut! Astăzi vom analiza un subiect foarte important care privește obiectele noastre. Aici, fără exagerare, putem spune că veți folosi aceste cunoștințe în fiecare zi în munca reală! Vom vorbi despre constructori.

Poate că ați auzit acest termen pentru prima dată, dar de fapt probabil ați folosit constructori, doar că nu l-ați observat singur :) Vom vedea asta mai târziu.

Ce sunt constructorii și de ce sunt necesari?

Să luăm în considerare două exemple. Public class Car ( model String; int maxSpeed; public static void main (String args) ( Car bugatti = new Car () ; bugatti. model = "Bugatti Veyron" ; bugatti. maxSpeed ​​​​​= 407 ; ) ) Am creat mașina noastră si instalat pentru el modelul si viteza maxima. Totuși, într-un proiect real, obiectul Car nu va avea evident 2 câmpuri. Și, de exemplu, 16 câmpuri! Public class Car ( model String; // model int maxSpeed; //viteza maxima//volumul motorului//numele proprietarului//numărul de locuri în cabină Salon de corziMaterial; // material interior asigurare booleană; //este asigurat//țara producătoare inttrunkVolume; // volumul portbagajului int accelerationTo100km; public static void main (String args) ( Mașină bugatti = mașină nouă () ; bugatti. culoare = "albastru" ; bugatti. accelerationTo100km = 3 ; bugatti. engineVolume = 6,3 ; bugatti. manufacturerCountry = "Italia" ; bugatti. ownerFirstName = " Amigo" ; bugatti. yearOfIssue = 2016 ; bugatti. asigurare = adevărat ; bugatti. preț = 2000000 ; bugatti. isNew = fals ; bugatti. placesInTheSalon = 2 ; bugatti. maxSpeed ​​​​= 407 ; bugatti. model = "Bugatti Veyron"; ) ) Am creat un nou obiect Car. O problema: avem 16 câmpuri, dar am inițializat doar 12! Încercați acum prin cod pentru a le găsi pe cele pe care le-am uitat! Nu atât de ușor, nu? Într-o astfel de situație, programatorul poate face cu ușurință o greșeală și poate sări peste inițializarea unui câmp. Ca urmare, comportamentul programului va deveni eronat: public class Car ( model String; // model int maxSpeed; //viteza maxima int roți; //lățimea discului dublu motorVolum; //volumul motorului Stringcolor; //color int yearOfIssue; //anul emiterii String proprietarFirstName; //nume proprietar String proprietarLastName; //numele proprietarului pret lung; //prețul boolean este Nou; //nou sau nu int placesInTheSalon; //numărul de locuri în cabină Salon de corziMaterial; // material interior asigurare booleană; //este asigurat Producător de șiruriȚara; //țara producătoare inttrunkVolume; // volumul portbagajului int accelerationTo100km; //accelerare până la 100 km/h în secunde public static void main (String args) ( Mașină bugatti = mașină nouă () ; bugatti. culoare = "albastru" ; bugatti. accelerationTo100km = 3 ; bugatti. engineVolume = 6,3 ; bugatti. manufacturerCountry = "Italia" ; bugatti. ownerFirstName = " Amigo" ; bugatti. yearOfIssue = 2016 ; bugatti. asigurare = adevărat ; bugatti. preț = 2000000 ; bugatti. isNew = fals ; bugatti. placesInTheSalon = 2 ; bugatti. maxSpeed ​​​​= 407 ; bugatti. model = "Bugatti Veyron"; System.out.println( "Model Bugatti Veyron. Dimensiunea motorului - "+ bugatti. motorVolum + ", portbagajul - " + bugatti. trunkVolum + ", salonul este făcut din"+ bugatti. salonMaterial + ", lățimea discului - "+ bugatti. roți + ". A fost achiziționat în 2018 de dl. "+ bugatti. proprietarLastName); ) ) Ieșire consolă: Modelul Bugatti Veyron. Dimensiune motor - 6.3, portbagaj - 0, interior din nul, latime roata - 0. A fost achizitionat in 2018 de domnul null Cumpărătorului tău care a plătit 2 milioane de dolari pentru o mașină, evident, nu-i va plăcea să fie numit „ domnule nul”! Dar serios, ca rezultat, programul nostru a ajuns cu un obiect creat incorect - o mașină cu o lățime a discului de 0 (adică fără discuri), un portbagaj lipsă, un interior dintr-un material necunoscut și chiar apartenență. cuiva care știe. Vă puteți imagina doar cum o astfel de eroare poate „trage” atunci când programul rulează! Trebuie să evităm cumva astfel de situații. Este necesar ca programul nostru să aibă o restricție: atunci când se creează un nou obiect mașină pentru el mereu trebuie specificate, de exemplu, modelul și viteza maximă. În caz contrar, nu permiteți crearea de obiecte. Această sarcină este ușor de gestionat funcții de constructor. Și-au primit numele pentru un motiv. Constructorul creează un fel de „schelet” al clasei, căruia fiecare nou obiect al clasei trebuie să îi corespundă. Pentru comoditate, să revenim la o versiune mai simplă a clasei Car cu două câmpuri. Având în vedere cerințele noastre, constructorul pentru clasa Car va arăta astfel: public Car (model String, int maxSpeed) ( this . model = model; this . maxSpeed ​​​​= maxSpeed; ) Și crearea obiectului arată acum astfel: public static void main (String args ) ( Car bugatti = mașină nouă ("Bugatti Veyron" , 407 ) ; ) cum este creat constructorul. Este similar cu o metodă obișnuită, dar nu are un tip de returnare. În acest caz, numele clasei este indicat în constructor, tot cu majusculă. În cazul nostru - Mașină . În plus, constructorul folosește un nou cuvânt cheie pentru tine acest. „this” în engleză – „this one”. Acest cuvânt se referă la un anumit subiect. Codul din constructor: public Car (Model String, int maxSpeed) ( acest . model = model; acest . maxSpeed ​​​​= maxSpeed; ) poate fi tradus aproape textual: „ model pentru această mașină (pe care o creăm în prezent) = argument model, care este specificat în constructor.maxSpeed ​​​​pentru această mașină (pe care o creăm) = la argumentul maxSpeed ​​​​din constructor." Și așa s-a întâmplat: public class Car ( model String; int maxSpeed; public Car (model String, int maxSpeed) ( this . model = model; this . maxSpeed ​​​​= maxSpeed; ) public static void main (String args) ( Car bugatti = mașină nouă ("Bugatti Veyron", 407) ; System. out. println (bugatti. model) ; System. out. println (bugatti. maxSpeed) ; ) ) Ieșire consolă: Bugatti Veyron 407 Constructorul a atribuit cu succes valorile dorite. Poate ați observat că un constructor este foarte asemănător cu o metodă obișnuită! Așa este: un constructor este o metodă, doar puțin specifică :) La fel ca într-o metodă, am transmis parametri constructorului nostru. Și la fel ca apelarea unei metode, apelarea unui constructor nu va funcționa dacă nu le specificați: public class Car ( model String; int maxSpeed; public Car (model String, int maxSpeed) ( this . model = model; this . maxSpeed ​​​​= maxSpeed; ) public static void main (String args) ( Car bugatti = new Car () ; //eroare! ) ) Vezi, constructorul a făcut ceea ce încercam să realizăm. Acum nu poți crea o mașină fără viteză sau fără model! Asemănările dintre constructori și metode nu se termină aici. La fel ca și metodele, constructorii pot fi suprasarcina. Imaginează-ți că ai 2 pisici acasă. L-ai luat pe unul dintre ei ca pisoi și ai adus a doua casă de pe stradă ca adult și nu știi exact câți ani are. Aceasta înseamnă că programul nostru ar trebui să poată crea pisici de două tipuri - cu un nume și vârstă pentru prima pisică și numai cu un nume - pentru a doua pisică. Pentru a face acest lucru, vom supraîncărca constructorul: public class Cat ( String name; int age; //pentru prima pisică //pentru a doua pisică public Cat (Nume șir) ( this . name = name; ) public static void main (String args) ( Cat barsik = new Cat ("Barsik" , 5 ) ; Cat streetCatNamedBob = new Cat ("Bob" ) ; ) ) la constructorul original cu parametrii „nume” și „vârstă”, am adăugat altul, doar cu numele. În același mod, am supraîncărcat metode în lecțiile anterioare. Acum putem crea cu succes ambele variante de pisici :)

Îți amintești, la începutul prelegerii, am spus că ai folosit deja constructori, dar nu ai observat asta? Si aici este. Faptul este că fiecare clasă din Java are un așa-numit constructor implicit. Nu ia niciun argument, dar se declanșează de fiecare dată când este creat orice obiect din orice clasă. public class Cat ( public static void main (String args) ( Cat smears = new Cat () ; ) ) La prima vedere, acest lucru este invizibil. Ei bine, au creat un obiect și l-au creat, unde este munca constructorului? Pentru a vedea acest lucru, să scriem direct un constructor gol pentru clasa Cat și în interiorul lui vom afișa o frază în consolă. Dacă este afișat, atunci constructorul a funcționat. public class Cat ( public Cat () ( System. out. println ("A creat o pisica!" ) ; ) public static void main (String args) ( Cat smears = new Cat () ; //aici a funcționat constructorul implicit } } Ieșire din consolă: A creat o pisică! Iată confirmarea! Constructorul implicit este întotdeauna prezent invizibil în clasele dvs. Dar trebuie să știi încă o caracteristică a acestuia. Constructorul implicit dispare din clasă atunci când creați un constructor cu argumente. Dovada acestui lucru, de fapt, am văzut-o deja mai sus. Aici, în acest cod: public class Cat ( String name; int age; public Cat (String name, int age) ( this . name = name; this . age = age; ) public static void main (String args) ( Cat barsik = new Cat () ; //eroare! ) ) Nu am putut crea o pisică fără nume și vârstă, deoarece am definit un constructor pentru Cat: șir + număr. Constructorul implicit imediat după aceea a dispărut din clasa. Prin urmare, asigurați-vă că rețineți: dacă aveți nevoie de mai mulți constructori în clasa dvs., inclusiv cel gol, trebuie creat separat. De exemplu, creăm un program pentru o clinică veterinară. Clinica noastră vrea să facă fapte bune și să ajute pisicile fără adăpost, despre care nu știm nici numele, nici vârsta. Atunci codul nostru ar trebui să arate astfel: public class Cat ( String name; int age; //pentru pisici domestice public Cat (Nume șir, vârstă int) ( this . name = name; this . age = age; ) //pentru pisici de stradă public Cat () ( ) public static void main (String args) ( Cat barsik = new Cat ("Barsik" , 5 ) ; Cat streetCat = new Cat () ; ) ) Acum că am scris explicit constructorul implicit, putem creează pisici de ambele tipuri :) Pentru un constructor (ca pentru orice metodă), ordinea argumentelor este foarte importantă. Să schimbăm argumentele nume și vârstă în constructorul nostru. public class Cat ( String name; int age; public Cat (int age, String name) ( this . name = name; this . age = age; ) public static void main (String args) ( Cat barsik = new Cat ("Barsik " , 10 ) ; //eroare! ) ) Eroare! Constructorul descrie clar: atunci când se creează un obiect Cat, acesta trebuie trecut număr și șir, în această ordine. Prin urmare, codul nostru nu funcționează. Asigurați-vă că aveți în vedere acest lucru și țineți cont de acest lucru atunci când vă creați propriile clase: public Cat (Nume șir, vârstă int) ( acest . nume = nume; acest . vârstă = vârstă; ) public Cat (înt age, String name) ( this . age = age; this .name = name; ) Aceștia sunt doi constructori complet diferiți! Dacă exprimi într-o singură propoziție răspunsul la întrebare De ce ai nevoie de un constructor?, poti spune: pentru a se asigura că obiectele sunt întotdeauna în starea corectă. Când utilizați constructori, toate variabilele dvs. vor fi inițializate corect și nu vor exista mașini cu viteza 0 și alte obiecte „greșite” în program. Utilizarea lor este foarte benefică în primul rând pentru programator însuși. Dacă inițializați singur câmpurile, există un risc mare să pierdeți ceva și să faceți o greșeală. Dar acest lucru nu se va întâmpla cu constructorul: dacă nu i-ați transmis toate argumentele necesare sau nu le-ați amestecat tipurile, compilatorul va da imediat o eroare. Separat, merită menționat că în interiorul constructorului nu ar trebui să puneți logica programului dvs. Pentru asta ai la dispozitie metode, în care puteți descrie toate funcționalitățile de care aveți nevoie. Să vedem de ce logica constructorului este o idee proastă: clasă publică CarFactory ( String name; int age; int carsCount; public CarFactory (String name, int age, int carsCount) ( this . name = name; this . age = age; this. carsCount = carsCount;system.out.println( „Ea a fost fondată” „În medie ea produce”+ (acest . carsCount/ this . age) + „mașini pe an” ); ) public static void main (String args) ( CarFactory ford = new CarFactory ("Ford" , 115 , 50000000 ) ; ) ) Avem o clasă CarFactory, descriind o fabrică de mașini. În interiorul constructorului, inițializam toate câmpurile și punem aici logica: imprimăm câteva informații despre fabrică în consolă. S-ar părea că nu este nimic în neregulă cu asta, programul a funcționat perfect. Ieșire din consolă: Fabrica noastră de mașini se numește Ford. A fost înființată acum 115 ani. În acea perioadă, a produs 50.000.000 de mașini În medie, produce 434.782 de mașini pe an. Dar, de fapt, am pus o bombă cu ceas. Și un astfel de cod poate duce foarte ușor la erori. Imaginează-ți că acum nu vorbim despre Ford, ci despre noua fabrică „Amigo Motors”, care există de mai puțin de un an și a produs 1000 de mașini: public class CarFactory ( String name; int age; int carsCount; public CarFactory (String) name, int age, int carsCount) ( this . name = nume; this . age = age; this . carsCount = carsCount; System. out. println ( „Fabrica noastră de mașini se numește”+ asta. Nume); Sistem. afară. println ( „Ea a fost fondată”+ asta. vârsta + „ani în urmă” ); Sistem. afară. println ( „În acest timp a fost produs”+ asta. carsCount + „mașini” ); Sistem. afară. println ( „În medie ea produce”+ (acest . carsCount/ this . age) + „mașini pe an” ); ) public static void main (String args) ( CarFactory ford = new CarFactory ("Amigo Motors" , 0 , 1000 ) ; ) ) Ieșire consolă: Fabrica noastră de mașini se numește Amigo Motors Exception în firul „principal” java.lang.ArithmeticException: / by zero A fost fondată acum 0 ani În acest timp, a produs 1000 de mașini la CarFactory. (CarFactory.java:15) la CarFactory.main(CarFactory.java:23) Procesul s-a încheiat cu codul de ieșire 1 Am ajuns! Programul s-a încheiat cu o eroare ciudată. Poți ghici care este motivul? Motivul este în logica pe care o punem în constructor. Mai exact, în această linie: System. afară. println ( „În medie ea produce”+ (acest . carsCount/ this . age) + „mașini pe an” ); Aici efectuăm un calcul și împărțim numărul de mașini produse la vârsta fabricii. Și întrucât fabrica noastră este nouă (adică are 0 ani), rezultatul este o împărțire cu 0, care este interzisă la matematică. Ca urmare, programul se încheie cu o eroare. Cum ar fi trebuit să procedăm? Mutați toată logica într-o metodă separată și apelați-o, de exemplu, printFactoryInfo() . Îi puteți trece un obiect CarFactory ca parametru. Puteți pune, de asemenea, toată logica acolo și, în același timp - procesarea eventualelor erori, ca a noastră cu zero ani. Fiecare a lui. Sunt necesari constructori pentru a seta corect starea unui obiect. Pentru logica de afaceri, avem metode. Nu amestecați unul cu celălalt. Iată câteva link-uri utile de unde puteți citi mai multe despre constructori:



Ți-a plăcut articolul? Împărtășește-l