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 preverjatierrno
. Č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
(vjava.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
ssporoč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čljivo
metode; 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 vjava.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čljivo
metode. 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čljivo
drugi 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čljivo
in 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:
- Uporabi
vrgel
izjavo, da vrže objekt izjeme. - 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.