Acest articol discută mecanismul de gestionare a excepțiilor utilizat în Java. O excepție în Java este un obiect care descrie o condiție excepțională care a apărut într-o parte a codului programului. Când apare o excepție, este creat un obiect al clasei Excepţie. Acest obiect este transmis metodei care procesează acest tip situatie exceptionala. Pot fi ridicate și excepții pentru a raporta anumite situații anormale.
Mecanismul de excepție în Java este susținut de cinci cuvinte cheie:
Mai jos este forma generală a unui bloc de gestionare a excepțiilor.
Încercați ( // bloc de cod ) catch (
În partea de sus a ierarhiei excepțiilor se află clasa Aruncabil, care este moștenit de la Obiect. Fiecare dintre tipurile de excepții este o subclasă de Throwable. Doi descendenți imediati ai clasei Throwable împart ierarhia subclaselor de excepție în două ramuri distincte. Ierarhia claselor este prezentată în figură.
Clasă Excepţie folosit pentru a descrie situații de excepție care trebuie surprinse de codul utilizatorului. Clasă Eroare este destinat să descrie situații excepționale care în condiții normale nu ar trebui să fie prinse într-un program de utilizator.
Obiectele de excepție sunt create automat de runtime Java atunci când apar anumite excepții. Un exemplu de program în care creăm o excepție la împărțirea la zero.
mostre de ambalaj; clasa TestException ( public static void main(String args) ( int d = 0; int a = 42 / d; System.out.println ("a = " + a); ) )
Următorul mesaj va fi imprimat pe consolă.
Excepție în firul „principal” java.lang.ArithmeticException: / prin zero la samples.TestException.main(TestException.java:8)
Rețineți că tipul de excepție aruncat nu a fost Excepţie si nu Aruncabil. Aceasta este o subclasă a clasei Excepţie, si anume: ArithmeticException, explicând ce eroare a apărut în timpul executării programului.
Să schimbăm clasa adăugând o metodă statică subrutină, în care vom crea aceeași situație excepțională.
mostre de ambalaj; clasă publică TestException ( static void subroutine() ( int d = 0; int a = 10 / d; System.out.println ("a = " + a); ) public static void main(String args) ( TestException.subroutine( ) )
Mesajul de execuție a programului arată cum se execută gestionarea excepțiilor sisteme Java imprimă conținutul întregii stive de apeluri.
Excepție în firul „principal” java.lang.ArithmeticException: / cu zero la samples.TestException.subroutine(TestException.java:8) la samples.TestException.main(TestException.java:14)
Pentru a proteja codul programului de excepții, trebuie să utilizați blocuri asociate cu cuvinte cheie incearca sa prinzi ; catch este plasat imediat după blocul de încercare. Blocul catch specifică tipul de excepție care trebuie tratată.
Clasa TestException ( public static void main(String args) ( try ( int d = 0; int a = 42 / d; ) catch (ArithmeticException e) ( System.out.println("diviziune cu zero"); ) ) )
Scopul celor mai bine concepute captură-secțiunile ar trebui să proceseze excepția apărută și să aducă variabilele programului într-o stare rezonabilă - astfel încât programul să poată fi continuat ca și cum nu ar fi apărut nicio eroare (în exemplul nostru, este afișat un avertisment - împărțire la zero).
ÎN în unele cazuri un bloc de cod poate arunca excepții diverse tipuri. Pentru a localiza procesarea unor astfel de situații, puteți folosi mai multe captură-partitii pentru unul încercați să blocați. Blocurile celor mai specializate clase de excepție trebuie să fie pe primul loc, deoarece nu se va ajunge la nicio subclasă dacă sunt plasate după superclasă.
Următorul exemplu prinde două tipuri diferite de excepții, cu acești doi handlere specializate urmate de o secțiune captură scop general, interceptând toate subclasele clasei Aruncabil.
Clasa MultiCatch ( static int c = ( 1 ); public static void main(String args) ( try ( int a = args.length; System.out.println("a = " + String.valueOf(a))); int b = 23 / a; c = 33; ) catch (ArithmeticException e) ( System.out.println("ArithmeticException: " + e.getMessage()); ) catch(ArrayIndexOutOfBoundsException e) ( System.out.println("ArrayIndexOutOfBound " + e.getMessage()); ) ) )
Acest exemplu, atunci când rulează fără parametri, ridică o excepție de împărțire la zero. Dacă în linie de comandă vor fi definiți unul sau mai mulți parametri, setând astfel „a” la o valoare mai mare decât zero, apoi va fi ridicată o excepție de index în afara limitelor ArrayIndexOutOfBounds. Mai jos sunt rezultatele acestui program care rulează în ambele moduri.
A = 0 div cu 0: java.lang.ArithmeticException: / cu zero a = 1 index matrice oob: java.lang.ArrayIndexOutOfBoundsException:33
Operatori încerca pot fi imbricate unul în celălalt. Dacă operatorul încerca nivel scăzut nicio sectiune captură corespunzătoare excepției aruncate, stiva va fi extinsă cu un pas mai sus și secțiunile catch ale instrucțiunii exterioare try vor fi verificate pentru a găsi un handler potrivit. Exemplu de imbricare a două declarații incearca sa prinzi unul în celălalt prin apelarea unei metode.
Clasa MultiNest ( static int c = ( 1 ); static void checkArray() ( încercați ( c = 33; ) catch(ArrayIndexOutOfBoundsException e) ( System.out.println "ArrayIndexOutOfBoundsException: " + e.getMessage()); ) ) public static void main(String args) ( try ( int a = args.length(); System.out.println("a = " + a); int b = 23 / a; checkArray(); ) catch (ArithmeticException e) ( System.out.println("ArithmeticException: " + e.getMessage()); ) ) )
Un program poate arunca în mod explicit o excepție folosind instrucțiunea arunca. După executarea instrucțiunii arunca procesul de execuție a programului este suspendat și instrucțiunile ulterioare nu sunt executate. JVM se uită la blocurile din apropiere încearcă...prind, corespunzătoare tipului de excepție, pentru „transfer control”. Dacă nu este găsit un bloc adecvat, handlerul de excepții va opri programul și va „tipări” starea stivei de apeluri.
Exemplu de excepție în care obiectul excepție este mai întâi aruncat, apoi instrucțiunea arunca ridică o excepție, după care se ridică din nou aceeași excepție - de data aceasta prin codul secțiunii care a prins-o prima dată captură.
Clasa TestThrow ( static void method() ( încercați ( throw new NullPointerException ("Excepție în metodă"); ) catch (NullPointerException e) ( System.out.println(e.getMessage()); throw e; ) ) public static void main(String args) ( try ( method(); ) catch(NullPointerException e) ( System.out.println("Catch inside main: " + e.getMessage()); ) ) )
Rezultatul rulării programului este prezentat mai jos.
Excepție în metodă Catch inside main: Excepție în metodă
Dacă o metodă poate arunca excepții pe care nu le gestionează ea însăși, trebuie să declare acest lucru, astfel încât alte metode care o apelează să se poată proteja de aceste excepții. Pentru a specifica o listă de excepții care pot fi ridicate printr-o metodă, utilizați cuvânt cheie aruncări.
Dacă metoda este explicită (adică folosind operatorul arunca) ridică o excepție, tipul clasei de excepție trebuie specificat în instrucțiune aruncăriîn declaraţia acestei metode. Luând în considerare acest lucru, sintaxa definiției unei metode ar trebui descrisă după cum urmează:
Clasa publică TestThrow ( static void method() aruncă IllegalAccessException ( try ( System.out.println ("în interiorul metodei")); aruncă o nouă IllegalAccessException ("Excepție în metodă"); ) catch (NullPointerException e) ( System.out.println( e.getMessage()); ) public static void main(String args) ( try ( method(); ) catch(IllegalAccessException e) ( System.out.println("Catch inside main: " + e.getMessage()) ;)))
Rezultatul exemplului:
Metoda interior Catch inside main: Excepție în metodă
În cazul în care este necesar să se garanteze executarea unei anumite secțiuni de cod, trebuie să utilizați cuvântul cheie in sfarsit. Utilizarea Comunicarii incearca... in sfarsit vă permite să vă asigurați că codul este executat indiferent de excepțiile aruncate și prinse, chiar și în cazurile în care metoda nu are o secțiune catch corespunzătoare excepției aruncate.
Fiecare secțiune încerca trebuie să fie conform cel puţin sau o secțiune captură sau bloc in sfarsit. Un bloc final este foarte util pentru închiderea fișierelor și eliberarea oricăror alte resurse care au fost păstrate pentru utilizare temporară la începutul execuției unei metode.
Mai jos este un exemplu de clasă cu două metode care se completează prin diverse motive, dar în ambele codul de secțiune este executat înainte de a ieși in sfarsit.
Clasa publică TestFinally ( static void methodA() ( încercați ( System.out.println ("în interiorul metodei A")); aruncați o nouă excepție RuntimeException ("Excepție în metoda A"); ) în cele din urmă ( System.out.println ("în final în interiorul metodeiA") ; ) ) static void methodB() ( try ( System.out.println("inside methodB"); return; ) finally ( System.out.println("finally inside methodB"); ) ) public static void main(String args ) ( încercați ( methodA(); ) catch (Excepția e) ( System.out.println(„Prinți excepția în interiorul principal”); ) methodB(); ) )
În exemplul de testare, este ridicată o excepție în metoda A. Dar înainte de a părăsi blocul prematur încerca, secțiunea rulează in sfarsit. Cea de-a doua metodă metodaB completează munca în încerca-blocare de către operator reveni, dar chiar înainte de a ieși din metodă, codul de program al blocului este executat in sfarsit. Rezultatul exemplului de testare:
În interiorul metodeiA, în cele din urmă, în interiorul metodeiA Prindeți excepția în interiorul principal în interiorul metodeiB, în final, în interiorul metodeiB
Gestionarea excepțiilor în Java oferă un mecanism extrem de puternic de gestionare programe complexe. Cuvinte cheie încercați, aruncați, prindeți vă permit să gestionați erorile și diversele situații anormale din program.
captură- design polimorf, i.e. catch by type parent captează excepțiile de orice tip care sunt Parent.
Clasa publică TestException ( public static void main(String args) ( try ( System.err.print ("nivel 0")); aruncă un nou RuntimeException (); System.err.print ("nivel 1"); ) catch (Excepție e ) ( // prind Exception CATCHING RuntimeException System.err.print("nivelul 2"); ) System.err.println("nivelul 3" ) )
Ca rezultat, vom vedea în consolă
Nivelul 0 Nivelul 2 Nivelul 3
Eroare și Excepţie din ramuri paralele de moştenire din Aruncabil, așa că prindeți un frate nu puteți prinde un alt frate.
Clasa publică TestError ( public static void main(String args) ( încercați ( System.err.println ("nivel 0")); dacă (adevărat) ( aruncă o nouă eroare (); ) System.err.println ("nivel 1") ") ; ) catch (Excepția e) ( System.err.println("nivelul 2"); ) System.err.println("nivelul 3" ) )
Rezultatul executării programului
Excepție de nivel 0 în firul „principal” java.lang.Error at TestError.main(TestFinally.java:8)
Pot exista mai multe declarații de excepții într-o metodă. Exemplu:
Import java.io.EOFException; import java.io.FileNotFoundException; clasă publică MultiException ( // declară excepții public static void main(String args) throws EOFException, FileNotFoundException ( if (System.currentTimeMillis() % 2 == 0) ( throw new EOFException(); ) else ( throw new FileNotFoundException(); ) ) )
Orice program va funcționa stabil doar dacă codul său sursă este depanat și nu conține condiții care ar putea provoca situații neașteptate. Procesul de detectare a eventualelor defecțiuni se realizează în etapa de programare. Pentru a face acest lucru, dezvoltatorul ia în considerare toate rezultatele posibile și încearcă să limiteze efectul erorii, astfel încât să nu perturbe funcționarea programului sau să îl provoace blocarea.
În Java, excepțiile pot fi cauzate de introducerea incorectă a utilizatorului, absența unei resurse necesare pentru rularea programului sau o întrerupere bruscă a rețelei. Pentru utilizarea confortabilă a aplicației create de dezvoltator, este necesar să se controleze apariția situațiilor de urgență. Consumatorul nu trebuie să aștepte ca un program blocat să se finalizeze, să piardă date din cauza excepțiilor necontrolate sau pur și simplu să primească mesaje frecvente că ceva a mers prost.
Ce trebuie să iei în considerare? Limbajul Java are propria sa funcționalitate încorporată de gestionare a excepțiilor. Bineînțeles, un procent mare de erori sunt surprinse în etapa de compilare, când sistemul raportează automat că este imposibil să-l mai folosești. Dar există și un tip de excepție care apare în timp ce programul rulează. Dezvoltatorul trebuie să fie capabil să anticipeze acest lucru și să proiecteze codul în așa fel încât să nu provoace o eroare, ci să o gestioneze într-un mod special sau a transferat controlul către o altă sucursală.
În Java, o astfel de captare a excepțiilor este impusă de compilator, deci probleme tipice sunt cunoscute și au propria lor schemă standard de execuție.
Cel mai mult exemplu simplu, în care puteți obține o excepție este diviziunea. În ciuda simplității sale, expresia poate conține zero ca divizor, ceea ce va duce la o eroare. Este bine dacă apariția sa poate fi prezisă mai devreme și prevenită. Dar această opțiune nu este întotdeauna disponibilă, așa că prinderea excepției trebuie organizată imediat când apare o „diviziune la zero”.
În Java, mecanismul de gestionare a erorilor arată astfel:
Cel mai simplu exemplu de creare a unei erori poate arăta astfel:
aruncă o nouă excepție NullPointerException();
Aici variabila a este verificată pentru inițializare, adică. dacă referința la obiect este nulă. Dacă apare o astfel de situație și este necesară o manipulare specială, o excepție este aruncată folosind throw new NullPointerException().
Când lucrați cu excepții, deseori trebuie să utilizați cuvinte cheie Java pentru a indica o anumită acțiune. ÎN limba dată Există cinci opțiuni de programare:
Aruncarea unei excepții în Java presupune în mod natural că aceasta va fi gestionată într-un mod special. Cel mai convenabil este să faceți acest lucru dacă o secțiune de cod este îngrădită într-un anumit bloc. Care poate conține o excepție. La executarea unui astfel de cod, mașina virtuală va găsi o situație neașteptată, va înțelege că se află într-un bloc critic și va transfera controlul în secțiunea de procesare.
În Java, codul este împachetat într-un bloc special de încercare, în cadrul căruia poate fi aruncată o excepție. Astfel, în el sunt plasate deodată mai multe situații neprevăzute, care vor fi prinse într-un singur loc, fără a se răspândi în întregul cod.
Codul cel mai tipic cu un bloc de procesare arată astfel:
//Aici va fi definit codul care poate arunca o exceptie
) catch (Exception_type_1 identifier_1) (
) catch (Exception_type_2 identifier_2) (
//Excepția este procesată aici, după tipul și condițiile acesteia;
Cuvântul cheie catch indică faptul că codul care este capturat de testul de excepție trebuie procesat așa cum este descris în continuare, cu condiția să se potrivească cu tipul său. Identificatorul poate fi folosit în cadrul unui bloc de cod de procesare ca argumente.
După cum a fost clar din capitolul anterior, blocurile catch captează excepțiile și le gestionează. Dar de foarte multe ori apare o situație în care trebuie executat un anumit cod, indiferent dacă au fost surprinse erori. Există în sfârșit un cuvânt cheie pentru asta. Este folosit pentru a incrementa diverse contoare, a închide fișiere sau a închide conexiunile de rețea.
Această secțiune prezintă mai multe blocuri de captură cu metode inventate pentru capturarea excepțiilor. De exemplu, codul conținut în try generează o situație neașteptată precum Cold. Apoi expresiile „Caught cold!” vor fi afișate în consolă. și „Este ceva de încurajat?” Adică blocul final este executat în orice caz.
Există de fapt o modalitate de a evita să alergi în cele din urmă. Este asociat cu oprirea mașinii virtuale. Puteți afla cum să implementați acest lucru pe Internet.
Throw aruncă o excepție. Sintaxa sa arată astfel:
arunca noua NewException();
Aici este creată o nouă excepție cu tipul NewException(). Tipul poate fi folosit deja inclus în biblioteci standard Clasele Java și cele definite anterior de producția proprie a dezvoltatorului.
Această construcție este inclusă în descrierea unei metode, care trebuie apoi apelată în cadrul unui bloc try pentru a o putea intercepta.
Ce trebuie făcut dacă în timpul procesului de dezvoltare apare o situație în care o metodă poate arunca o excepție, dar nu o poate gestiona corect. Pentru a face acest lucru, semnătura metodei specifică cuvântul aruncă și tipul posibilei excepții.
Această etichetă este un fel de indicator pentru dezvoltatorii clienți că metoda nu este capabilă să gestioneze propria excepție. În plus, dacă tipul de eroare este testabil, compilatorul vă va forța să indicați acest lucru în mod explicit.
În versiunea 7 Java, dezvoltatorii au inclus o inovație atât de importantă precum procesarea unui bloc de încercare cu resurse.
Multe obiecte create în Java trebuie să fie închise după ce sunt folosite pentru a economisi resurse. Anterior, trebuia să luăm în considerare acest lucru și să oprim manual astfel de instanțe. Acum au interfața AutoClosable. Ajută la închiderea automată a obiectelor deja folosite plasate într-un bloc de încercare. Datorită acestei abordări, scrierea codului a devenit mai convenabilă, iar lizibilitatea sa a crescut semnificativ.
Creatorii limbajului de programare descris au ținut cont de multe aspecte atunci când au proiectat tipuri de situații neprevăzute. Cu toate acestea, nu va fi posibil să preveniți toate rezultatele posibile ale evenimentelor, astfel încât Java implementează capacitatea de a vă defini propriile excepții care sunt potrivite în mod specific pentru nevoile unui anumit cod.
Cel mai simplu mod de a-l crea este de a moșteni de la obiectul care este cel mai potrivit pentru context.
Aceasta moștenește de la Exception, o clasă care este folosită pentru a defini excepții personalizate. MyException are doi constructori - unul implicit, al doilea cu un argument msg de tip String.
Apoi clasa publică FullConstructors implementează o metodă f a cărei semnătură conține MyException. Acest cuvânt cheie înseamnă că f poate arunca o excepție tip Java MyException. Apoi, în corpul metodei, informațiile text sunt trimise în consolă și MyException în sine este generată folosind throw.
A doua metodă este ușor diferită de prima prin faptul că, atunci când este creată o excepție, i se transmite un parametru șir, care se va reflecta în consolă atunci când este prins. În principal, puteți vedea că f() și g() sunt plasate într-un bloc try și cuvântul cheie catch este configurat pentru a captura MyException. Rezultatul procesării va fi rezultatul unui mesaj de eroare către consolă:
Astfel am reușit să adăugăm excepții Java create de noi înșine.
Ca toate obiectele din Java, excepțiile sunt, de asemenea, moștenite și au structura ierarhică. Elementul rădăcină al tuturor erorilor aruncate în acest limbaj de programare este clasa java.lang.Throwable. Două tipuri sunt moștenite de la acesta - Eroare și Excepție.
Eroare - notifică despre erori criticeși reprezintă excepțiile neverificate ale Java. Interceptarea și prelucrarea unor astfel de date au loc în majoritatea cazurilor în stadiul de dezvoltare și nu trebuie să fie implementate în codul final al aplicației.
Clasa cel mai frecvent utilizată pentru crearea și analiza excepțiilor este Exception. Care, la rândul său, este împărțit în mai multe ramuri, inclusiv RuntimeException. RuntimeException se referă la excepțiile de rulare, adică cele care apar în timp ce programul rulează. Toate clasele moștenite de la acesta sunt neverificabile.
În Java, excepțiile, a căror listă este prezentată mai jos, sunt utilizate cel mai des, așa că merită să descrieți fiecare dintre ele mai detaliat:
Aceste exemple sunt tipuri de excepții Java nebifate. Și așa arată cele bifate:
Vorbind despre excepțiile frecvent întâlnite, trebuie remarcat faptul că interpretarea lor în timpul dezvoltării poate fi interpretată incorect. Mai jos este o listă scurtă care explică mai detaliat când poate apărea o situație neașteptată.
NullPointerException. Prima dată când se aruncă o excepție este atunci când este accesată o referință de obiect care este nulă. Acest lucru se aplică și metodelor instanței nule a clasei. NullPointerException poate fi, de asemenea, aruncată dacă lungimea matricei este nulă. Verificarea periodică a obiectelor pentru null va ajuta la evitarea unor astfel de situații.
ArrayIndexOutOfBoundsException. Orice program nu poate exista fără a folosi matrice. În consecință, accesul frecvent la acestea poate genera și erori. O excepție apare atunci când dezvoltatorul încearcă să acceseze un element de matrice care nu se află în lista de indexuri. De exemplu, valoarea cerută este mai mare decât lungimea sau mai mică decât zero. Foarte des apare ca urmare a faptului că numărarea în matrice începe de la zero.
Gestionarea excepțiilor Java − instrument puternic mediu, care facilitează foarte mult munca programatorului și îi permite să creeze cod curat și fără erori. Statutul și reputația companiei dezvoltatoare depind de cât de bine și de stabil funcționează aplicația.
Desigur, în programe mai mult sau mai puțin simple este mult mai ușor de urmărit situațiile de urgență. Dar în complexele automate mari cu câteva sute de mii de linii, acest lucru este posibil doar ca urmare a depanării și testării îndelungate.
Pentru excepțiile Java, care provoacă erori în unele aplicații, unele companii oferă recompense pasionaților care le găsesc. Sunt apreciate în special cele care provoacă o încălcare a politicii de securitate a pachetului software.
Excepțiile sau situațiile excepționale (stările) sunt erori care apar într-un program în timpul funcționării acestuia.
Toate excepțiile din Java sunt obiecte. Prin urmare, acestea pot fi generate nu numai automat atunci când apare o situație excepțională, ci și create de însuși dezvoltatorul.
Ierarhia claselor de excepție:
Excepțiile sunt împărțite în mai multe clase, dar toate au un strămoș comun - clasa Throwable. Descendenții săi sunt subclasele Excepție și Eroare.
Excepțiile sunt rezultatul unor probleme dintr-un program care sunt, în principiu, rezolvabile și previzibile. De exemplu, împărțirea la zero a avut loc în numere întregi.
Erorile reprezintă mai mult decât probleme serioase, care, conform specificației Java, nu ar trebui încercat să fie procesat în program propriu, deoarece sunt legate de probleme la nivel JVM. De exemplu, excepții de acest fel apar dacă memoria este disponibilă pentru mașină virtuală. Programul încă nu va putea oferi memorie suplimentară pentru JVM.
În Java, toate excepțiile sunt împărțite în trei tipuri: excepții verificate (verificate) și excepții nebifate (neverificate), care includ erori (Erori) și excepții de rulare (RuntimeExceptions, un descendent al clasei Exception).
Excepțiile certificate sunt erori care pot și ar trebui gestionate într-un program toți descendenții clasei Exception (dar nu RuntimeException) aparțin acestui tip;
Gestionarea excepțiilor poate fi făcută folosind instrucțiunile try...catch sau transferată în partea externă a programului. De exemplu, o metodă poate trece excepții care apar în ea mai sus în ierarhia apelurilor fără a o gestiona singură.
Excepțiile nebifate nu necesită tratare, dar puteți gestiona RuntimeExceptions dacă doriți.
Să compilam și să rulăm următorul program:
Clasa Main ( public static void main(String args) ( int a = 4; System.out.println(a/0); ) )
La lansare, pe consolă va fi afișat următorul mesaj:
Excepție în firul „principal” java.lang.ArithmeticException: / prin zero la Main.main(Main.java:4)
Mesajul arată clasa excepției care a apărut - ArithmeticException. Această excepție poate fi gestionată:
Clasa Main ( public static void main(String args) ( int a = 4; try ( System.out.println(a/0); ) catch (ArithmeticException e) ( System.out.println ("A avut loc un eveniment nevalid operație aritmetică"); } } }
Acum, în loc de un mesaj de eroare standard, va fi executat un bloc catch, al cărui parametru este obiectul e clasa corespunzătoare excepției (obiectului în sine i se poate da orice nume; va fi necesar dacă vrem să aruncăm din nou această excepție cu forța, de exemplu, astfel încât să poată fi verificată de un alt handler).
Blocul try conține fragmentul programului în care ar putea apărea o excepție.
O singură încercare poate corespunde mai multor blocuri de captură cu diferite clase de excepții.
Import java.util.Scanner; clasa Main ( public static void main(String args) ( int m = (-1,0,1); Scanner sc = new Scanner (System.in); try ( int a = sc.nextInt(); m[a] = 4/a; System.out.println(m[a]); catch (ArithmeticException e) ( System.out.println("A avut loc o operație aritmetică ilegală"); („Acces prin index de matrice nevalid”);
Dacă, după lansarea programului prezentat, utilizatorul intră de la tastatura 1 sau 2, programul va rula fără a crea excepții.
Dacă utilizatorul introduce 0, o ArithmeticException va fi lansată și gestionată de primul bloc catch.
Dacă utilizatorul introduce 3, va apărea o excepție a clasei ArrayIndexOutOfBoundsException (matrice în afara limitelor) și va fi procesată de al doilea bloc catch.
Dacă utilizatorul introduce un număr care nu este întreg, de exemplu, 3.14, atunci va apărea o excepție a clasei InputMismatchException (nepotrivire tip valoare de intrare) și va fi aruncată în format de eroare standard, deoarece nu am gestionat-o în niciun fel .
Cu toate acestea, puteți adăuga un handler pentru clasa Exception, deoarece această clasă este clasa părinte pentru toate celelalte excepții controlate, va intercepta oricare dintre ele (inclusiv InputMismatchException).
Import java.util.Scanner; clasa Main ( public static void main(String args) ( int m = (-1,0,1); int a = 1; Scanner sc = new Scanner(System.in); try ( a = sc.nextInt();); m = 4/a; System.out.println(m[a]); catch (ArithmeticException e) ( System.out.println("A avut loc o operație aritmetică ilegală"); ) catch (ArrayIndexOutOfBoundsException e) ( System.out. println(„Manevrarea unui index de matrice nevalid”); catch (Excepție e) ( System.out.println(„A apărut o altă excepție”);
Deoarece excepțiile sunt construite pe o ierarhie de clase și subclase, mai întâi ar trebui să încercați să gestionați excepții mai specifice și abia apoi pe cele mai generale. Adică, dacă am plasat primul (și nu al treilea) bloc cu gestionarea excepțiilor din clasa Excepție, nu am vedea niciodată niciun mesaj de eroare în afară de „S-au produs o altă excepție” (toate excepțiile ar fi capturate imediat de acest bloc și nu ar ajunge la rest) .
O adăugare opțională pentru a încerca...catch blocks poate fi un bloc final. Comenzile plasate în acesta vor fi executate în orice caz, indiferent dacă apare sau nu o excepție. În ciuda faptului că atunci când apare o excepție netratată, partea de program rămasă după generarea acestei excepții nu este executată. De exemplu, dacă a apărut o excepție în timpul unor calcule de lungă durată, blocul final poate fi folosit pentru a afișa sau stoca rezultate intermediare.
2010, Alexey Nikolaevich Kostin. Departamentul TIDM, Facultatea de Matematică, Universitatea Pedagogică de Stat din Moscova.
Bună, Habr! Vă prezint atenției o traducere a articolului Fixing 7 Common Java Exception Handling Mistakes de Thorben Janssen.
Gestionarea unei excepții este una dintre cele mai comune, dar nu neapărat una dintre cele mai ușoare sarcini. Acesta este încă unul dintre subiectele discutate frecvent în rândul echipelor cu experiență și există câteva bune practici și greșeli comune de care ar trebui să fii conștient.
Iată câteva lucruri de evitat atunci când gestionați excepții în aplicația dvs.
Public void doNotSpecifyException() aruncă excepție ( doSomething(); ) public void doSomething() aruncă NumberFormatException, IllegalArgumentException ( // face ceva )
Dar asta nu înseamnă că trebuie să o faci. Specificarea Excepție sau Throwable face aproape imposibil să le gestionați corect atunci când apelați metoda dvs. Singura informație pe care o primește metoda dvs. de apelare este că ceva ar putea merge prost. Dar nu distribuiți nicio informație despre niciun eveniment excepțional care ar putea avea loc. Ascundeți aceste informații în spatele motivelor generice pentru a arunca excepții. Devine și mai rău atunci când aplicația dvs. se modifică în timp. Aruncarea excepțiilor generice ascunde toate modificările excepțiilor la care apelantul trebuie să se aștepte și să le gestioneze. Acest lucru poate duce la mai multe erori neașteptate care trebuie găsite în cazul de testare în loc de o eroare a compilatorului.
Public void specifySpecificExceptions() aruncă NumberFormatException, IllegalArgumentException ( doSomething(); )
Acest lucru oferă mai multe beneficii. Această abordare vă permite să gestionați fiecare clasă de excepții în mod diferit și vă împiedică să identificați excepții la care nu vă așteptați.
Dar rețineți că primul bloc catch care se ocupă de clasa de excepție sau una dintre super-clasele sale îl va prinde. Așa că asigurați-vă că prindeți mai întâi clasa cea mai specifică. În caz contrar, IDE-urile dvs. vor afișa o eroare sau un avertisment despre un bloc de cod inaccesibil.
Încercați ( doSomething(); ) catch (NumberFormatException e) ( // gestionează NumberFormatException log.error(e); ) catch (IllegalArgumentException e) ( // gestionează IllegalArgumentException log.error(e); )
1. Nu aveți suficiente informații despre cazul de utilizare pe care apelantul metodei dvs. dorește să îl implementeze. O excepție poate face parte din comportamentul așteptat și poate fi gestionată de client. În acest caz, nu este nevoie să îl înregistrați. Acest lucru va adăuga un mesaj de eroare fals la fișierul jurnal, care ar trebui să fie filtrat de echipa dumneavoastră de operațiuni.
2. Mesajul jurnal nu furnizează nicio informație care să nu facă deja parte din excepția în sine. Urmărirea și urmărirea stivei sale ar trebui să conțină toate informatiile necesare despre un eveniment excepțional. Mesajul descrie acest lucru și conține următorul stivă informatii detaliate despre clasa, metoda și linia în care a avut loc.
3. Puteți înregistra aceeași excepție de mai multe ori când o înregistrați în fiecare bloc de captură care o prinde. Acest lucru va strica statisticile din instrumentul dvs. de monitorizare și va face fișierul jurnal dificil de citit pentru echipa dvs. de operațiuni și dezvoltare.
Public void doEvenMore() ( try ( doMore(); ) catch (NumberFormatException e) ( // gestionează NumberFormatException ) catch (IllegalArgumentException e) ( // gestionează IllegalArgumentException ) ) public void doMore() aruncă NumberFormatException, IllegalArgumentException (doArgumentException(doSomethException) ) public void doSomething() aruncă NumberFormatException, IllegalArgumentException ( // face ceva )
Ele funcționează practic ca o instrucțiune Go To, deoarece anulează execuția unui bloc de cod și merg la primul bloc catch care se ocupă de excepție. Acest lucru face codul foarte greu de citit.
Nu sunt la fel de eficiente ca structuri generale Comenzi Java. După cum sugerează și numele, ar trebui să le folosiți numai pentru evenimente excepționale, iar JVM-ul nu le optimizează în același mod ca alt cod. Deci, este mai bine să folosiți condițiile potrivite pentru a vă întrerupe buclele sau declarațiile if-else care cod de blocuri trebuie executat.
Când aruncați o nouă excepție, ar trebui să setați întotdeauna excepția originală ca cauză. În caz contrar, veți pierde mesajul și urma stivei care descrie evenimentul excepțional care a provocat excepția dvs. Clasa Exception și toate subclasele sale oferă mai multe metode de constructor care iau excepția originală ca parametru și o setează ca cauză.
Public void doNotGeneralizeException() aruncă o excepție ( try ( doSomething(); ) catch (NumberFormatException e) ( aruncă o nouă excepție (e); ) catch (IllegalArgumentException e) ( aruncă o nouă excepție (e); ) )
Așa cum puteți vedea în următorul fragment de cod, chiar dacă știți ce excepții ar putea arunca o metodă, nu le puteți prinde pur și simplu. Trebuie să capturați clasa generică Exception și apoi să verificați tipul cauzei acesteia. Acest cod nu este doar greu de implementat, dar este și greu de citit. Devine și mai rău dacă combinați această abordare cu eroarea 5. Aceasta elimină toate informațiile despre evenimentul excepțional.
Încercați ( doNotGeneralizeException(); ) catch (Exception e) ( if (e.getCause() instanceof NumberFormatException) ( log.error("NumberFormatException: " + e); ) else if (e.getCause() instanceof IllegalArgumentException) ( jurnal .error("Excepție neașteptată: " + e); else ( log.error ("Excepție neașteptată: " + e); ) )
Deci care abordare este cea mai bună?
Încercați ( doSomething(); ) catch (NumberFormatException e) ( aruncați o nouă excepție MyBusinessException (e, ErrorCode.CONFIGURATION_ERROR); ) catch (IllegalArgumentException e) (aruncă o nouă MyBusinessException (e, ErrorCode.UNEXPECTED); )
Public void persistCustomer(Customer c) throws MyPersistenceException ( // persist a Customer ) public void manageCustomer(Customer c) throws MyBusinessException ( // gestionează un Client try ( persistCustomer(c); ) catch (MyPersistenceException e) ( throw new MyBusinessException , e.getCode()); ) public void createCustomer(Customer c) aruncă MyApiException ( // creează o încercare de client ( manageCustomer(c); ) catch (MyBusinessException e) ( aruncă o nouă excepție MyApiException(e, e.getCode()) ) )
Este ușor de observat că aceste clase de excepții suplimentare nu oferă niciun beneficiu. Ele introduc pur și simplu straturi suplimentare care învelesc excepția. Și deși ar fi distractiv să împachetezi un cadou în o mulțime de hârtie colorată, nu este o abordare bună a dezvoltării software.
Prin urmare, aveți grijă la numărul de clase de excepții personalizate pe care le introduceți. Ar trebui să vă întrebați întotdeauna dacă noua clasă aduce excepții Informații suplimentare sau alte beneficii. În cele mai multe cazuri, nu aveți nevoie de mai mult de un nivel de excepții personalizate pentru a realiza acest lucru.
Public void persistCustomer(Customer c) ( // persistă un Client ) public void manageCustomer(Customer c) aruncă MyBusinessException ( // gestionează un Client aruncă un nou MyBusinessException(e, e.getCode()); ) public void createCustomer(Client c) aruncă MyBusinessException ( // creează un Customer manageCustomer(c); )
Ultima actualizare: 30.10.2015
Erorile pot apărea adesea în timpul execuției programului și nu neapărat din vina dezvoltatorului. Unele dintre ele sunt greu de prevăzut sau anticipat, iar uneori chiar imposibile. De exemplu, se poate rupe brusc conexiune la rețea la transferul unui fișier. Astfel de situații se numesc excepții.
Limbajul Java oferă instrumente speciale pentru a gestiona astfel de situații. Un astfel de mijloc este încercarea... prinderea... construcția în sfârșit. Când apare o excepție într-un bloc try, controlul trece la blocul catch, care poate gestiona excepția. Dacă nu se găsește un astfel de bloc, utilizatorului îi este afișat un mesaj de excepție netratată și execuția ulterioară a programului este oprită. Și pentru a preveni o astfel de oprire, trebuie să utilizați un bloc try..catch. De exemplu:
Int numere = new int; numere=45; System.out.println(numerele);
Deoarece matricea noastră numere poate conține doar 3 elemente, la executarea instrucțiunii numere=45, consola va afișa o excepție și programul se va termina. Acum să încercăm să gestionăm această excepție:
Try( int numere = new int; numere=45; System.out.println(numere); ) catch(Exception ex)(ex.printStackTrace(); ) System.out.println("Program terminat");
Când se utilizează un bloc try...catch, toate instrucțiunile dintre instrucțiunile try și catch sunt executate mai întâi. Dacă o excepție apare brusc într-un bloc try, ordinul normal de execuție se oprește și trece la instrucțiunea catch. Prin urmare, când execuția programului ajunge la numerele de linie=45; , programul se va opri și va merge la blocul catch
Expresia catch are următoarea sintaxă: catch (type_excepție nume_variabilă) . ÎN în acest caz, este declarată o variabilă ex, care este de tip Excepție. Dar dacă excepția care apare nu este o excepție de tipul specificat în instrucțiunea catch, atunci nu este procesată, iar programul pur și simplu îngheață sau aruncă un mesaj de eroare.
Dar, deoarece tipul Exception este clasa de bază pentru toate excepțiile, expresia catch (Exception ex) va gestiona aproape toate excepțiile. Gestionarea excepției în acest caz se reduce la tipărirea urmei stivei de erori pe consolă folosind metoda printStackTrace() definită în clasa Exception.
După ce blocul catch termină execuția, programul își continuă munca, executând toate celelalte instrucțiuni după blocul catch.
Construcția try..catch poate avea și un bloc final. Cu toate acestea, acest bloc este opțional și poate fi omis atunci când se gestionează excepții. Blocul final este executat indiferent dacă apare sau nu o excepție în blocul try:
Încercați( int numere = int nou; numere = 45; System.out.println(numere); ) catch(Exception ex)(ex.printStackTrace(); ) finally( System.out.println("În cele din urmă blocați"); ) System.out.println("Program finalizat");
Există multe tipuri diferite de excepții în Java și le putem diferenția gestionarea prin includerea blocurilor de captură suplimentare:
Int numere = new int; try( numere=45; numere=Integer.parseInt("gfd"); ) catch(ArrayIndexOutOfBoundsException ex)( System.out.println("Matrice în afara limitelor"); ) catch(NumberFormatException ex)( System.out.println ("Eroare la conversia din șir în număr");
Dacă primim o excepție anumit tip, apoi merge la blocul de captură corespunzător.
Puteți utiliza instrucțiunea throw pentru a indica că au apărut excepții într-un program. Adică, folosind acest operator, noi înșine putem crea o excepție și o ridicăm în timpul execuției. De exemplu, în programul nostru introducem un număr și vrem să aruncăm o excepție dacă numărul este mai mare de 30:
Pachetul firstapp; import java.util.Scanner; clasă publică FirstApp ( public static void main(String args) ( try( Scanner in = new Scanner(System.in); int x = in.nextInt(); if(x>=30)( throw new Exception ("Numărul x trebuie să fie mai mic de 30"); ) ) catch(Excepție ex)( System.out.println(ex.getMessage()); ) System.out.println("Program terminat"); ) )
Aici, pentru a crea un obiect excepție, se folosește constructorul clasei Exception, căruia îi este transmis mesajul de excepție. Și dacă numărul x este mai mare decât 29, atunci va fi aruncată o excepție și controlul va trece la blocul catch.
În blocul catch, putem obține mesajul de excepție folosind metoda getMessage().