Cum să gestionați excepțiile Java în modul corect

Cum să gestionați excepțiile Java în modul corect

Ca începător de programare, conceptul de manipularea excepțiilor poate fi greu să vă înfășurați capul. Nu că conceptul în sine este dificil, dar terminologia îl poate face să pară mai avansat decât este. Și este o caracteristică atât de puternică încât este predispusă la abuz și abuz.





În acest articol, veți afla care sunt excepțiile, de ce sunt importante, cum să le utilizați și greșelile obișnuite de evitat. Majoritatea limbajelor moderne au un fel de gestionare a excepțiilor, așa că, dacă treceți vreodată de la Java, puteți lua majoritatea acestor sfaturi cu dvs.





Înțelegerea excepțiilor Java

În Java, un excepție este un obiect care indică ceva anormal (sau „excepțional”) care a avut loc în timpul rulării aplicației. Astfel de excepții sunt aruncat , ceea ce înseamnă practic că se creează un obiect de excepție (similar cu modul în care sunt „ridicate” erorile).





Frumusețea este că poți captură excepții aruncate, care vă permite să faceți față stării anormale și să permiteți aplicației dvs. să ruleze în continuare ca și cum nimic nu ar fi mers prost. De exemplu, în timp ce un pointer nul în C ar putea bloca aplicația, Java vă permite să aruncați și să prindeți

NullPointerException

s înainte ca o variabilă nulă să aibă șansa de a provoca un accident.



Amintiți-vă, o excepție este doar un obiect, dar cu o caracteristică importantă: trebuie extinsă de la

Exception

clasa sau orice subclasă de





Exception

. În timp ce Java are tot felul de excepții încorporate, puteți crea propriile dvs., dacă doriți. Unele dintre cele mai frecvente excepții Java include:

  • NullPointerException
  • NumberFormatException
  • IllegalArgumentException
  • RuntimeException
  • IllegalStateException

Ce se întâmplă atunci când arunci o excepție?





În primul rând, Java analizează metoda imediată pentru a vedea dacă există cod care să gestioneze tipul de excepție pe care l-ați aruncat. Dacă un handler nu există, se uită la metoda care a apelat metoda curentă pentru a vedea dacă există un handle acolo. Dacă nu, se uită la metoda care a apelat acea metoda, apoi metoda următoare etc. Dacă excepția nu este surprinsă, aplicația imprimă o urmă de stivă și apoi se blochează. (De fapt, este mai nuanțat decât simpla blocare, dar acesta este un subiect avansat dincolo de sfera acestui articol.)

LA urme de stivă este o listă cu toate metodele pe care Java le-a parcurs în timp ce căuta un handler de excepție. Iată cum arată o urmă de stivă:

Exception in thread 'main' java.lang.NullPointerException
at com.example.myproject.Book.getTitle(Book.java:16)
at com.example.myproject.Author.getBookTitles(Author.java:25)
at com.example.myproject.Bootstrap.main(Bootstrap.java:14)

Putem culege multe din asta. În primul rând, excepția aruncată a fost o

NullPointerException

. A avut loc în

getTitle()

metoda de pe linia 16 din Book.java. Această metodă a fost apelată de la

getBookTitles()

pe linia 25 din Author.java. Acea metoda a fost apelată de la

main()

pe linia 14 din Bootstrap.java. După cum puteți vedea, cunoașterea tuturor acestor lucruri facilitează depanarea.

Dar, din nou, adevăratul beneficiu al excepțiilor este că puteți „gestiona” starea anormală prin prinderea excepției, corectarea lucrurilor și reluarea aplicației fără blocare.

Utilizarea excepțiilor Java în cod

Să spunem că ai

someMethod()

care ia un număr întreg și execută o logică care s-ar putea rupe dacă întregul este mai mic de 0 sau mai mare de 100. Acesta ar putea fi un loc bun pentru a arunca o excepție:

cum se pune Instagram în ordine cronologică
public void someMethod(int value) {
if (value 100) {
throw new
IllegalArgumentException

Pentru a prinde această excepție, trebuie să mergeți unde

someMethod()

se numește și folosește bloc de încercare :

public void callingMethod() {
try {
someMethod(200);
someOtherMethod();
} catch (IllegalArgumentException e) {
// handle the exception in here
}
// ...
}

Totul în încerca blocul se va executa în ordine până când se aruncă o excepție. De îndată ce se lansează o excepție, toate instrucțiunile ulterioare sunt omise și logica aplicației sare imediat la captură bloc.

În exemplul nostru, intrăm în blocul try și apelăm imediat

someMethod()

. Deoarece 200 nu este între 0 și 100, un

IllegalArgumentException

este aruncat. Aceasta pune capăt imediat executării

someMethod()

, omite restul logicii din blocul try (

someOtherMethod()

nu este apelat niciodată) și reia executarea în cadrul blocului de captură.

Ce s-ar întâmpla dacă am suna

someMethod(50)

in schimb? The

IllegalArgumentException

nu ar fi aruncat niciodată.

someMethod()

s-ar executa normal. Blocarea try se va executa normal, apelând

someOtherMethod()

când someMethod () completează. Cand

someOtherMethod()

se termină, blocul de captură ar fi omis și

callingMethod()

ar continua.

Rețineți că puteți avea mai multe blocuri de captură pentru fiecare bloc de încercare:

public void callingMethod() {
try {
someMethod(200);
someOtherMethod();
} catch (IllegalArgumentException e) {
// handle the exception in here
} catch (NullPointerException e) {
// handle the exception in here
}
// ...
}

De asemenea, rețineți că este opțional in cele din urma blocul există și:

public void method() {
try {
// ...
} catch (Exception e) {
// ...
} finally {
// ...
}
}

Codul dintr-un bloc final este mereu executat indiferent de ce. Dacă aveți o declarație return în blocul try, blocul final este executat înainte de a reveni din metodă. Dacă aruncați o altă excepție în blocul de captură, blocul final este executat înainte ca excepția să fie aruncată.

Ar trebui să utilizați blocul în cele din urmă atunci când aveți obiecte care trebuie curățate înainte ca metoda să se termine. De exemplu, dacă ați deschis un fișier în blocul try și ulterior ați lansat o excepție, blocul final vă permite să închideți fișierul înainte de a părăsi metoda.

Rețineți că puteți avea un bloc în cele din urmă fără un bloc de captură:

public void method() {
try {
// ...
} finally {
// ...
}
}

Acest lucru vă permite să faceți orice curățare necesară, permițând în același timp excepțiilor aruncate pentru a propaga stiva de invocare a metodei (adică nu doriți să gestionați excepția aici, dar trebuie totuși să curățați mai întâi).

Excepții verificate vs. Excepții nelimitate în Java

Spre deosebire de majoritatea limbajelor, Java face distincție între verificate excepțiile și excepții necontrolate (de exemplu, C # are numai excepții nebifate). O excepție verificată trebuie sa să fie prins în metoda în care se aruncă excepția sau altfel codul nu se va compila.

Pentru a crea o excepție bifată, extindeți din

Exception

. Pentru a crea o excepție nebifată, extindeți din

RuntimeException

.

Orice metodă care aruncă o excepție bifată trebuie să denote acest lucru în semnătura metodei folosind aruncă cuvânt cheie. De când Java este încorporat

IOException

este o excepție verificată, următorul cod nu se va compila:

public void wontCompile() {
// ...
if (someCondition) {
throw new IOException();
}
// ...
}

Mai întâi trebuie să declarați că aruncă o excepție bifată:

public void willCompile() throws IOException {
// ...
if (someCondition) {
throw new IOException();
}
// ...
}

Rețineți că o metodă poate fi declarată ca aruncând o excepție, dar niciodată nu aruncă o excepție. Chiar și așa, excepția va trebui totuși capturată sau altfel codul nu va fi compilat.

Când ar trebui să utilizați excepții bifate sau nebifate?

Documentația oficială Java are un pagina despre această întrebare . Rezumă diferența cu o succintă regulă de bază: „Dacă se poate aștepta în mod rezonabil ca un client să se recupereze dintr-o excepție, faceți din acesta o excepție verificată. Dacă un client nu poate face nimic pentru a se recupera de la excepție, faceți din acesta o excepție necontrolată. '

Dar acest ghid poate fi depășit. Pe de o parte, excepțiile verificate rezultă într-un cod mai robust. Pe de altă parte, niciun alt limbaj nu a verificat excepțiile în același mod ca Java, ceea ce arată două lucruri: unul, caracteristica nu este suficient de utilă pentru ca alte limbi să o fure și două, puteți trăi absolut fără ele. În plus, excepțiile verificate nu se joacă frumos cu expresiile lambda introduse în Java 8.

Liniile directoare pentru utilizarea excepțiilor Java

Excepțiile sunt utile, dar ușor de utilizat și abuzat. Iată câteva sfaturi și cele mai bune practici pentru a vă ajuta să evitați să le faceți mizerie.

  • Preferați excepții specifice excepțiilor generale. Utilizați NumberFormatException peste IllegalArgumentException când este posibil, altfel utilizați IllegalArgumentException peste RuntimeException cand este posibil.
  • Nu prinde niciodată Throwable ! | | + _ | clasa se extinde de fapt Exception , iar blocul de captare funcționează de fapt cu Throwable sau orice clasă care se extinde Throwable. Cu toate acestea, | | + _ | clasa se extinde și Throwable și nu vreți niciodată să prindeți un Error deoarece Throwable indică probleme grave irecuperabile.
  • Nu prinde niciodată Error ! Error extinde Exception , deci orice bloc care prinde InterruptedException va prinde și Exception , și aceasta este o excepție foarte importantă cu care nu doriți să vă deranjați (mai ales în aplicații multi-thread), cu excepția cazului în care știți ce faceți. Dacă nu știți ce excepție să prindeți, luați în considerare să nu prindeți nimic.
  • Utilizați mesaje descriptive pentru a ușura depanarea. Când aruncați o excepție, puteți furniza un Exception mesaj ca argument. Acest mesaj poate fi accesat în blocul de captură folosind InterruptedException , dar dacă excepția nu este prinsă niciodată, mesajul va apărea și ca parte a urmăririi stivei.
  • Încercați să nu prindeți și să ignorați excepțiile. Pentru a evita inconvenientul excepțiilor verificate, o mulțime de programatori începători și leneși vor configura un blocaj de captură, dar îl vor lăsa gol. Rău! Manevrați-l întotdeauna cu grație, dar dacă nu puteți, cel puțin imprimați o urmă de stivă, astfel încât să știți că a fost aruncată excepția. Puteți face acest lucru folosind String metodă.
  • Feriți-vă de utilizarea excesivă a excepțiilor. Când ai un ciocan, totul arată ca un cui. Când aflați mai întâi despre excepții, vă puteți simți obligat să transformați totul într-o excepție ... până la punctul în care cea mai mare parte a fluxului de control al aplicației dvs. se reduce la gestionarea excepțiilor. Amintiți-vă, excepțiile sunt destinate aparițiilor „excepționale”!

Acum ar trebui să fiți suficient de confortabil, cu excepții, pentru a înțelege ce sunt, de ce sunt utilizate și cum să le încorporați în propriul cod. Dacă nu înțelegeți pe deplin conceptul, este în regulă! Mi-a luat ceva timp să „fac clic” în capul meu, așa că nu simți că trebuie să te grăbești. Nu vă grăbiți.

Aveți întrebări? Cunoașteți alte sfaturi legate de excepție pe care le-am ratat? Distribuiți-le în comentariile de mai jos!

Acțiune Acțiune Tweet E-mail Cum să creați o diagramă de flux de date pentru a vizualiza datele oricărui proiect

Diagramele fluxului de date (DFD) ale oricărui proces vă ajută să înțelegeți modul în care datele curg de la sursă la destinație. Iată cum să-l creați!

Citiți în continuare
Subiecte asemănătoare
  • Programare
  • Java
Despre autor Joel Lee(1524 articole publicate)

Joel Lee este redactor-șef al MakeUseOf din 2018. Are un B.S. în informatică și peste nouă ani de experiență profesională în redactare și editare.

cum să piratezi camera web a cuiva
Mai multe de la Joel Lee

Aboneaza-te la newsletter-ul nostru

Alăturați-vă newsletter-ului pentru sfaturi tehnice, recenzii, cărți electronice gratuite și oferte exclusive!

Faceți clic aici pentru a vă abona