Stabilirea unei excepții în parametrii metodei, dev64

Să presupunem că avem o metodă de clasă, în anumite condiții, aruncă o excepție. Poate parametrii metoda specifica o excepție că această metodă va arunca? Această întrebare, aparent simplu, dar acest lucru nu este atât de ușor pe cât pare.

De exemplu, următorul cod, arătând excepțiile de instalare, pune în aplicare imediat două manipulare excepție antipattern:

În primul rând, această metodă aruncă direct de clasă excepție. care rupe complet ierarhia normală de manipulare excepție. În al doilea rând, el pierde cauza rădăcină, din cauza care, de fapt, o excepție este aruncată. Cu alte cuvinte, în acest caz, cauza este IOException e. dar, în cazul în care excepția de nivel superior vor fi procesate și tipărite l stektreys, IOException s în trasarea stivei va fi. Aceasta este a doua problemă. Rezolva ambele probleme pot aplica abordarea prezentată mai jos:

În acest caz, aruncarea nu numai excepție. și tipul specific de excepție a trecut, metoda generic utilizat. O a doua problemă cauza rădăcină este rezolvată printr-o metodă initCause (clasa Throwable). initCause () expune cauza rădăcină de excepție. initCause () este proiectat astfel încât să puteți expune cauza rădăcină doar o singură dată. Nu poate fi numit din nou. Prin urmare, se pare, este numit initCause (). în schimb setCause (). Mai jos este un test de unitate care demonstrează utilizarea metodei care rezultă:

Ca urmare, o stektreys imprimate:


exceptions.MyException: Aceasta este o excepție mea
la exceptions.MyBusinessClassTest.test (MyBusinessClassTest.java:11)
.
Cauzate de: java.io.IOException: IOException cauza
la exceptions.MyBusinessClass.doOrThrow (MyBusinessClass.java:9)
. 27 mai

Ie Acesta arată că, în Tracy-stiva au rădăcină cauza «IOException cauza».

Având în vedere modificarea utilă mai sus a codului va fi înlocuit pe Exception Dispensabil. din cauza celor două subclase de Dispensabil doar una, excepție. Acesta special conceput pentru a fi utilizat de către programatori, precum și utilizarea aparentă a Dispensabil are un miros de cod.
Cu alte cuvinte, T se extinde de excepție, în schimb Dispensabil:

Ce această abordare poate fi un inconvenient? Conform celor mai bune practici pentru utilizarea excepțiilor (a se vedea. De exemplu, Dzhosh Bloh «eficientă Java»), cu excepția necesității de a menține cât mai mult posibil de informații utile care pot indica cauza erorii. De exemplu, este util pentru a crea un mesaj de excludere, cu acest mesaj conține potențial în schimbare părți. De exemplu:

Aici vom face conținutul mesajului din cadrul ValidationException catch-bloc. În acest cod, nu este nimic greșit, el este absolut corect. Cu toate acestea, în cazul în care creați o excepție, astfel utilizând metoda descrisă mai sus, de exemplu, după cum urmează:

se dovedește că vom crea un obiect excepție de fiecare dată când este executat codul. indiferent dacă eroarea este de fapt va întâmpla sau nu. Însăși crearea obiectului nu este atât de rău (aceasta este o operațiune foarte ieftine în Java), dar formatarea mesajului poate fi potențial costisitoare. Cele mai puternice limbi, cum ar fi Scala lui, problema poate fi rezolvată foarte simplu.

Diferența este doar prezența => în lista parametrilor din a doua metodă. Acest parametru e în al doilea exemplu de realizare este apelul prin nume sunt parametri a căror valoare va fi calculată numai atunci când metoda de utilizare vor fi îndeplinite în cadrul organismului, cu potențial de mai multe ori. Utilizarea acestor metode nu este diferită:

Diferența se manifestă în performanță. În primul caz ValidationException obiect va fi creat în orice caz, în al doilea - numai atunci când este necesar, și anume, când apare o eroare.

Din păcate, Java nu oferă un astfel de mecanism convenabil de evaluare leneș. Dar Java și Scala - Turing-complet, astfel încât Java poate fi pus în aplicare la fel ca și în Scala 🙂 Pentru aceasta vom folosi un model foarte popular - furnizor. Declararea de interfață:

și ne vom asigura că metoda noastră orThrow luată ca argument este ExceptionProvider. și nu Excepție gol:

Acum, crearea de obiecte excepție are loc numai atunci când este cu adevărat necesar. Utilizați orThrow metoda () poate, de exemplu, după cum urmează:

Se pare foarte greoaie, dar nu este o problemă, cel puțin din două motive. În primul rând, în următoarea versiune de Java (Java 8) mult-așteptata lambda va fi adăugat la limba, ceea ce va reduce codul de mai sus la acest lucru:

Nu mult mai mult decât Scala. Furnizorii de servicii de al doilea rând, poate fi captată, de exemplu, folosind reflexii:

Acest furnizor creează o excepție de o anumită clasă cu mesajul specificat, formatat folosind argumentele date:

Este clar că, pentru ca aceasta să funcționeze, la excluderea clasei trebuie să fie un constructor cu un singur argument șir de caractere.

Este folosit este un fel destul de evident:

Acum, codul a devenit destul de ușor de citit și nu desfășoară operațiuni inutile cu probleme, și este foarte flexibil.

Alte articole pe Java, consultați subiectul Java