1. Inițializarea variabilelor
După cum știți deja, puteți declara mai multe variabile în clasa dvs. și nu doar să le declarați, ci și să le inițializați imediat cu valorile lor inițiale.
Și aceleași variabile pot fi inițializate și într-un constructor. Aceasta înseamnă că, în teorie, acestor variabile li se pot atribui valori de două ori. Exemplu
Cod | Notă |
---|---|
|
Variabilei age i se atribuie o valoare inițială Valoarea inițială este suprascrisă Variabila vârstă își stochează valoarea inițială. |
|
Acest lucru este permis: primul constructor va fi apelat |
|
Acest lucru este permis: al doilea constructor va fi apelat |
Iată ce se întâmplă când Cat cat = new Cat("Whiskers", 2);
este executat:
Cat
Se creează un obiect- Toate variabilele de instanță sunt inițializate cu valorile lor inițiale
- Constructorul este apelat și codul său este executat.
Cu alte cuvinte, variabilele primesc mai întâi valorile inițiale și abia apoi este executat codul constructorului.
2. Ordinea inițializării variabilelor dintr-o clasă
Variabilele nu sunt doar inițializate înainte de rularea constructorului, ci sunt inițializate într-o ordine bine definită: ordinea în care sunt declarate în clasă.
Să ne uităm la un cod interesant:
Cod | Notă |
---|---|
|
Acest cod nu se va compila, deoarece la momentul a
creării variabilei nu există încă b
și c
variabile. Dar vă puteți scrie codul după cum urmează - acest cod se va compila și va rula foarte bine.
Cod | Notă |
---|---|
|
0 0+2 0+2+3 |
Dar rețineți că codul dvs. trebuie să fie transparent pentru alți dezvoltatori. Este mai bine să nu folosiți astfel de tehnici, deoarece afectează lizibilitatea codului.
Aici trebuie să ne amintim că înainte ca variabilelor să li se atribuie o valoare, acestea au o valoare implicită . Pentru int
tip, acesta este zero.
Când JVM inițializează a
variabila, va atribui pur și simplu valoarea implicită pentru tipul int: 0.
Când ajunge la b
, variabila a va fi deja cunoscută și va avea o valoare, așa că JVM-ul îi va atribui valoarea 2.
Și când ajunge la c
variabilă, variabilele a
și b
vor fi deja inițializate, astfel încât JVM-ul va calcula cu ușurință valoarea inițială pentru c
: 0+2+3.
Dacă creați o variabilă în interiorul unei metode, nu o puteți utiliza decât dacă i-ați atribuit anterior o valoare. Dar acest lucru nu este valabil pentru variabilele unei clase! Dacă o valoare inițială nu este atribuită unei variabile a unei clase, atunci i se atribuie o valoare implicită.
3. Constante
În timp ce analizăm modul în care sunt create obiectele, merită să atingem inițializarea constantelor, adică variabilele cu modificatorul final
.
Dacă o variabilă are final
modificatorul, atunci trebuie să i se atribuie o valoare inițială. Știți deja acest lucru și nu este nimic surprinzător.
Dar ceea ce nu știți este că nu trebuie să atribuiți valoarea inițială imediat dacă o atribuiți în constructor. Acest lucru va funcționa foarte bine pentru o variabilă finală. Singura cerință este ca, dacă aveți mai mulți constructori, atunci unei variabile finale trebuie să i se atribuie o valoare în fiecare constructor.
Exemplu:
public class Cat
{
public final int maxAge = 25;
public final int maxWeight;
public Cat (int weight)
{
this.maxWeight = weight; // Assign an initial value to the constant
}
}
4. Cod într-un constructor
Și mai multe note importante despre constructori. Mai târziu, pe măsură ce continuați să învățați Java, veți întâlni lucruri precum moștenirea, serializarea, excepții etc. Toate influențează munca constructorilor în grade diferite. Nu are sens să ne adâncim acum în aceste subiecte, dar suntem obligați să le atingem măcar.
De exemplu, iată o remarcă importantă despre constructori. În teorie, puteți scrie cod de orice complexitate într-un constructor. Dar nu face asta. Exemplu:
|
Deschideți un flux de citire a fișierului Citiți fișierul într-o matrice de octeți Salvați matricea de octeți ca șir Afișați conținutul fișierului pe ecran |
În constructorul clasei FilePrinter, am deschis imediat un flux de octeți pe un fișier și am citit conținutul acestuia. Acesta este un comportament complex și poate duce la erori.
Dacă nu ar exista un astfel de dosar? Ce se întâmplă dacă ar exista probleme cu citirea fișierului? Dacă ar fi prea mare?
Logica complexă implică o probabilitate mare de erori și asta înseamnă că codul trebuie să gestioneze corect excepțiile.
Exemplul 1 — Serializare
Într-un program standard Java, există o mulțime de situații în care nu ești cel care creează obiecte din clasa ta. De exemplu, să presupunem că decideți să trimiteți un obiect prin rețea: în acest caz, mașina Java însăși vă va converti obiectul într-un set de octeți, îl va trimite și va recrea obiectul din setul de octeți.
Dar apoi să presupunem că fișierul dvs. nu există pe celălalt computer. Va exista o eroare în constructor și nimeni nu o va gestiona. Și asta este destul de capabil să provoace terminarea programului.
Exemplul 2 — Inițializarea câmpurilor unei clase
Dacă constructorul clasei dumneavoastră poate arunca excepții verificate, adică este marcat cu cuvântul cheie throws, atunci trebuie să prindeți excepțiile indicate în metoda care creează obiectul dumneavoastră.
Dar dacă nu există o astfel de metodă? Exemplu:
Cod | Notă |
---|---|
|
Acest cod nu se va compila. |
Constructorul FilePrinter
clasei poate arunca o excepție bifată , ceea ce înseamnă că nu puteți crea un FilePrinter
obiect fără a-l încadra într-un bloc try-catch. Și un bloc try-catch poate fi scris doar într-o metodă
5. Constructorul clasei de bază
În lecțiile anterioare, am discutat puțin despre moștenire. Din păcate, discuția noastră completă despre moștenire și OOP este rezervată pentru nivelul dedicat OOP, iar moștenirea constructorilor este deja relevantă pentru noi.
Dacă clasa ta moștenește o altă clasă, un obiect al clasei părinte va fi încorporat într-un obiect al clasei tale. În plus, clasa părinte are propriile variabile și propriii ei constructori.
Asta înseamnă că este foarte important pentru tine să știi și să înțelegi cum sunt inițializate variabilele și cum sunt apelați constructorii atunci când clasa ta are o clasă părinte și moștenești variabilele și metodele acesteia.
Clase
Cum știm ordinea în care variabilele sunt inițializate și sunt chemați constructorii? Să începem prin a scrie codul pentru două clase. Unul îl va moșteni pe celălalt:
Cod | Notă |
---|---|
|
Clasa ChildClass moștenește ParentClass clasa. |
Trebuie să determinăm ordinea în care variabilele sunt inițializate și sunt apelați constructorii. Logarea ne va ajuta să facem acest lucru.
Logare
Înregistrarea este procesul de înregistrare a acțiunilor efectuate de un program pe măsură ce rulează, prin scrierea lor în consolă sau într-un fișier.
Este destul de simplu să determinați că constructorul a fost apelat: în corpul constructorului, scrieți un mesaj pe consolă. Dar cum vă puteți da seama dacă o variabilă a fost inițializată?
De fapt, nici acest lucru nu este foarte dificil: scrieți o metodă specială care va returna valoarea folosită pentru a inițializa variabila și înregistrați inițializarea. Iată cum ar putea arăta codul:
Cod final
|
Creați un ChildClass obiect Această metodă scrie textul transmis în consolă și, de asemenea, îl returnează. Declarați ParentClass clasa Display text și, de asemenea, inițializați variabilele cu ea. Scrieți un mesaj că constructorul a fost apelat. Ignorați valoarea returnată. Declarați ChildClass clasa Display text și, de asemenea, inițializați variabilele cu ea. Scrieți un mesaj că constructorul a fost apelat. Ignorați valoarea returnată. |
Dacă executați acest cod, textul va fi afișat pe ecran după cum urmează:
Ieșirea în consolă a metodeiMain.print() |
---|
|
Deci vă puteți asigura personal întotdeauna că variabilele unei clase sunt inițializate înainte ca constructorul să fie apelat. O clasă de bază este inițializată complet înainte de inițializarea clasei moștenite.
GO TO FULL VERSION