Programiranje

Izjeme v Javi, 1. del: Osnove ravnanja z izjemami

Izjeme Java so vrste knjižnic in jezikovne funkcije, ki se uporabljajo za predstavitev in obravnavo okvar programa. Če ste želeli razumeti, kako je napaka predstavljena v izvorni kodi, ste prišli na pravo mesto. Poleg pregleda izjem v Javi vam bom predstavil tudi jezikovne funkcije Jave za metanje predmetov, preizkušanje kode, ki morda ne bo uspelo, lovljenje vrženih predmetov in čiščenje kode Java po vrnjeni izjemi.

V prvi polovici te vadnice boste spoznali osnovne značilnosti jezika in tipe knjižnic, ki obstajajo že od Jave 1.0. V drugi polovici boste odkrili napredne zmogljivosti, predstavljene v novejših različicah Java.

Upoštevajte, da so primeri kode v tej vadnici združljivi z JDK 12.

prenos Prenesite kodo Prenesite izvorno kodo, na primer programe v tej vadnici. Ustvaril Jeff Friesen za JavaWorld.

Kaj so izjeme Java?

Napaka se zgodi, ko normalno delovanje Java programa prekine nepričakovano vedenje. Ta razlika je znana kot izjema. Program na primer poskuša odpreti datoteko, da prebere njeno vsebino, vendar datoteka ne obstaja. Java izjeme razvrsti v nekaj vrst, zato si oglejmo vsako.

Preverjene izjeme

Java izjeme, ki izhajajo iz zunanjih dejavnikov (na primer manjkajoče datoteke), razvrsti kot preverjene izjeme. Prevajalnik Java preveri, ali so take izjeme obravnava (popravljeno), če se pojavijo ali dokumentirajo, da jih je treba obravnavati drugje.

Obravnavalci izjem

An upravljalec izjem je zaporedje kode, ki obravnava izjemo. Zaslišuje kontekst - kar pomeni, da bere vrednosti, shranjene iz spremenljivk, ki so bile v obsegu v času, ko se je zgodila izjema - in nato uporabi tisto, kar se nauči, da obnovi program Java v tok običajnega vedenja. Na primer, obdelovalec izjem lahko prebere shranjeno ime datoteke in uporabnika pozove, naj nadomesti manjkajočo datoteko.

Izjeme med izvajanjem (nepreverjeno)

Recimo, da program skuša deliti celo število s celo število 0. Ta nezmožnost ponazarja drugo vrsto izjeme, in sicer a izjema med izvajanjem. Za razliko od preverjenih izjem izjeme med izvajanjem običajno izvirajo iz slabo napisane izvorne kode in bi jih zato moral popraviti programer. Ker prevajalnik ne preveri, ali so izjeme med izvajanjem obdelane ali dokumentirane, da jih je treba obdelati drugje, si lahko izjemo med izvajanjem predstavljate kot nepreverjena izjema.

O izjemah med izvajanjem

Program lahko spremenite tako, da bo obravnaval izjemo med izvajanjem, vendar je bolje popraviti izvorno kodo. Izjeme med izvajanjem pogosto izhajajo iz posredovanja neveljavnih argumentov knjižničnim metodam; klicno kodo je treba popraviti.

Napake

Nekatere izjeme so zelo resne, ker ogrožajo zmožnost nadaljevanja izvajanja programa. Na primer, program poskuša dodeliti pomnilnik iz JVM, vendar ni dovolj prostega pomnilnika, da bi zadostil zahtevi. Druga resna situacija se zgodi, ko program skuša datoteko razreda naložiti prek Class.forName () klic metode, vendar je datoteka razreda poškodovana. Tovrstna izjema je znana kot napaka. Nikoli ne poskušajte sami obravnavati napak, ker JVM od njih morda ne bo mogel obnoviti.

Izjeme v izvorni kodi

Izjema je lahko v izvorni kodi predstavljena kot napačna koda ali kot predmet. Predstavil bom oboje in vam pokazal, zakaj so predmeti boljši.

Kode napak v primerjavi s predmeti

Programski jeziki, kot je C, uporabljajo celoštevilsko kode napak predstavljati neuspeh in razloge za neuspeh - tj. izjeme. Tu je nekaj primerov:

if (chdir ("C: \ temp")) printf ("Ni mogoče spremeniti v začasni imenik:% d \ n", napačno); FILE * fp = fopen ("C: \ temp \ foo"); if (fp == NULL) printf ("Ni mogoče odpreti foo:% d \ n", napačno);

C-ji chdir () Funkcija (spremeni imenik) vrne celo število: 0 ob uspehu ali -1 ob neuspehu. Podobno tudi C-ji fopen () (datoteka odprta) vrne neveljavno kazalec (celoštevilski naslov) do a MAPA struktura uspeha ali ničelni (0) kazalec (predstavljen s konstanto NIČ) ob okvari. V obeh primerih morate za določitev izjeme, ki je povzročila napako, prebrati globalno errno koda napake na podlagi števila spremenljivk.

Kode napak povzročajo nekaj težav:

  • Cela števila so brez pomena; ne opisujejo izjem, ki jih predstavljajo. Na primer, kaj pomeni 6?
  • Povezovanje konteksta s kodo napake je nerodno. Na primer, morda boste želeli izpisati ime datoteke, ki je ni bilo mogoče odpreti, toda kam boste shranili ime datoteke?
  • Cela števila so poljubna, kar lahko pri branju izvorne kode povzroči zmedo. Na primer, določitev če (! chdir ("C: \ temp")) (! pomeni NE) namesto če (chdir ("C: \ temp")) za preizkus okvare je bolj jasno. Vendar je bilo 0 označeno, da označuje uspeh, in tako če (chdir ("C: \ temp")) mora biti naveden za preskus odpovedi.
  • Kode napak je preveč enostavno prezreti, kar lahko privede do napake. Na primer, programer lahko določi chdir ("C: \ temp"); in prezreti če (fp == NULL) preverite. Poleg tega programerju ni treba preverjati errno. Če programa ne preizkusi zaradi napake, se obnaša občasno, kadar katera od funkcij vrne indikator okvare.

Da bi rešila te težave, je Java sprejela nov pristop k obravnavi izjem. V Javi predmete, ki opisujejo izjeme, kombiniramo z mehanizmom, ki temelji na metanju in lovljenju teh predmetov. Nekaj ​​prednosti uporabe predmetov v primerjavi s kodo napake za označevanje izjem:

  • Predmet je mogoče ustvariti iz razreda s pomenljivim imenom. Na primer, FileNotFoundException (v java.io paket) je bolj smiseln kot 6.
  • Predmeti lahko shranjujejo kontekst na različnih poljih. Na primer, v polja predmeta lahko shranite sporočilo, ime datoteke, ki je ni bilo mogoče odpreti, zadnji položaj, kjer operacija razčlenitve ni uspela, in / ali druge elemente.
  • Ne uporabljate če izjave za preizkus okvare. Namesto tega se izjemenski predmeti vržejo v vodnik, ki je ločen od programske kode. Posledično je izvorno kodo lažje brati in manj verjetno, da bo napačna.

Dobavljivo in njeni podrazredi

Java ponuja hierarhijo razredov, ki predstavljajo različne vrste izjem. Ti razredi temeljijo na java.lang paketov Mečljivo razred, skupaj s svojimi Izjema, RuntimeException, in Napaka podrazredi.

Mečljivo je končni superrazred za izjeme. Samo predmeti, ustvarjeni iz Mečljivo in njegove podrazrede lahko vržemo (in nato ujamemo). Takšni predmeti so znani kot metanje.

A Mečljivo objekt je povezan z podrobno sporočilo ki opisuje izjemo. Za ustvarjanje a je na voljo več konstruktorjev, vključno s spodaj opisanim parom Mečljivo predmet s podrobnim sporočilom ali brez:

  • Dobavljivo () ustvari a Mečljivo brez podrobnih sporočil. Ta konstruktor je primeren za situacije, ko ni konteksta. Na primer, samo želite vedeti, da je kup prazen ali poln.
  • Dobavljivo (sporočilo v nizu) ustvari a Mečljivo s sporočilo kot podrobno sporočilo. To sporočilo lahko pošlje uporabniku in / ali ga zabeleži.

Mečljivo zagotavlja String getMessage () za vrnitev podrobnega sporočila. Ponuja tudi dodatne uporabne metode, ki jih bom predstavil kasneje.

Razred izjem

Mečljivo ima dva neposredna podrazreda. Eden od teh podrazredov je Izjema, ki opisuje izjemo, ki izhaja iz zunanjega dejavnika (na primer poskus branja iz neobstoječe datoteke). Izjema razglasi iste konstruktorje (z enakimi seznami parametrov) kot Mečljivo, in vsak konstruktor prikliče svoj Mečljivo kolega. Izjema podeduje Mečljivometode; ne navaja nobenih novih metod.

Java ponuja številne razrede izjem, ki so neposredno podrazredni Izjema. Tu so trije primeri:

  • CloneNotSupportedException signalizira poskus kloniranja predmeta, katerega razred ne izvaja datoteke Klonirano vmesnik. Obe vrsti sta v java.lang paket.
  • IOException signalizira, da je prišlo do neke vrste I / O okvare. Ta vrsta se nahaja v java.io paket.
  • ParseException signalizira, da je pri razčlenjevanju besedila prišlo do napake. To vrsto najdete v java.text paket.

Upoštevajte, da vsak Izjema ime podrazreda se konča z besedo Izjema. Ta konvencija olajša prepoznavanje namena predavanja.

Običajno boste podrazred Izjema (ali enega od njegovih podrazredov) z lastnimi razredi izjem (katerih imena naj se končajo z Izjema). Tu je nekaj primerov podrazredov po meri:

javni razred StackFullException razširja Exception {} javni razred EmptyDirectoryException razširja Exception {private String directoryName; javni EmptyDirectoryException (sporočilo v nizu, ime v nizu imenika) {super (sporočilo); this.directoryName = ImeName; } javni String getDirectoryName () {return directoryName; }}

Prvi primer opisuje razred izjem, ki ne zahteva podrobnega sporočila. Privzeto prikliče konstruktor noargument Izjema (), ki se sklicuje Dobavljivo ().

Drugi primer opisuje izjemen razred, katerega konstruktor zahteva podrobno sporočilo in ime praznega imenika. Konstruktor prikliče Izjema (sporočilo v nizu), ki prikliče Dobavljivo (sporočilo v nizu).

Predmeti, izdelani iz Izjema ali enega od njegovih podrazredov (razen za RuntimeException ali enega od njegovih podrazredov) so preverjene izjeme.

Razred RuntimeException

Izjema je neposredno podrazvrščena z RuntimeException, ki opisuje izjemo, ki je najverjetneje posledica slabo napisane kode. RuntimeException razglasi iste konstruktorje (z enakimi seznami parametrov) kot Izjema, in vsak konstruktor prikliče svoj Izjema kolega. RuntimeException podeduje Mečljivometode. Ne navaja nobenih novih metod.

Java ponuja številne razrede izjem, ki so neposredno podrazredni RuntimeException. Naslednji primeri so vsi člani java.lang paket:

  • ArithmeticException označuje nezakonito aritmetično operacijo, na primer poskus delitve celotnega števila z 0.
  • IllegalArgumentException signalizira, da je bil metodi poslan nezakonit ali neprimeren argument.
  • NullPointerException signalizira poskus klica metode ali dostopa do polja primerka prek ničelne reference.

Predmeti, izdelani iz RuntimeException ali eden od njegovih podrazredov je nepreverjene izjeme.

Razred napake

Mečljivodrugi neposredni podrazred je Napaka, ki opisuje resno (celo nenormalno) težavo, ki jo razumna aplikacija ne bi smela rešiti - na primer zmanjšanje pomnilnika, preplavitev sklada JVM ali poskus nalaganja razreda, ki ga ni mogoče najti. Všeč mi je Izjema, Napaka razglasi enake konstruktorje Mečljivo, podeduje Mečljivoin ne prijavi nobene lastne metode.

Lahko se prepoznate Napaka podrazredi konvencije, s katerimi se njihova imena razredov končajo Napaka. Primeri vključujejo OutOfMemoryError, Napaka povezave, in StackOverflowError. Vse tri vrste spadajo v java.lang paket.

Metanje izjem

Funkcija knjižnice C obvesti klicno kodo o izjemi z nastavitvijo globalne errno spremenljivko na kodo napake in vrnitev kode napake. Nasprotno pa metoda Java vrže predmet. Vedeti, kako in kdaj metati izjeme, je bistveni vidik učinkovitega programiranja Java. Metanje izjeme vključuje dva osnovna koraka:

  1. Uporabi vrgel izjavo, da vrže objekt izjeme.
  2. Uporabi meti klavzula o obveščanju prevajalnika.

Kasnejši razdelki se bodo osredotočili na lovljenje izjem in čiščenje po njih, najprej pa se naučimo več o metanju.

Izjava o metu

Java ponuja vrgel stavek, da vrže predmet, ki opisuje izjemo. Tu je sintaksa vrgel izjava:

vrgel mečljiv;

Predmet, ki ga je identificiral mečljiv je primerek Mečljivo ali katerega koli njegovega podrazreda. Vendar ponavadi vržete le predmete, ki so ustvarjeni iz podrazredov Izjema ali RuntimeException. Tu je nekaj primerov:

vrzi novo FileNotFoundException ("datoteke ni mogoče najti" + ime datoteke); vrzi novo IllegalArgumentException ("argument, poslan v štetje, je manjši od nič");

Vrzljivka se iz trenutne metode vrne v JVM, ki preveri, ali je ta metoda primerna. Če je ni mogoče najti, JVM sprosti sklad klicev metode in išče najbližjo klicno metodo, ki lahko obvlada izjemo, ki jo opisuje metanje. Če najde to metodo, prenese metanje na obdelavo metode, katere koda se izvede za obravnavo izjeme. Če ni mogoče najti nobene metode za obravnavo izjeme, se JVM konča z ustreznim sporočilom.

Klavzula o metih

Ko vržete preverjeno izjemo iz metode, morate obvestiti prevajalnika. To storite tako, da dodate a meti klavzula v glavo metode. Ta klavzula ima naslednjo skladnjo:

meti checkExceptionClassName (, checkExceptionClassName)*

A meti klavzula je sestavljena iz ključne besede meti čemur sledi seznam imen razredov preverjenih izjem, izločenih iz metode, z vejico. Tu je primer:

javna statična void main (String [] args) vrže ClassNotFoundException {if (args.length! = 1) {System.err.println ("uporaba: java ... classfile"); vrnitev; } Class.forName (args [0]); }

Ta primer poskuša naložiti datoteko razreda, opredeljeno z argumentom ukazne vrstice. Če Class.forName () ne najde datoteke razreda, vrže datoteko java.lang.ClassNotFoundException objekt, ki je preverjena izjema.

Preverjena polemika o izjemi

The meti klavzula in preverjene izjeme so sporne. Mnogi razvijalci sovražijo, da so prisiljeni določiti meti ali obravnavati preverjene izjeme. Več o tem lahko preberete v članku Ali so preverjene izjeme dobre ali slabe? objava v spletnem dnevniku.

$config[zx-auto] not found$config[zx-overlay] not found