„Java“ išimtys yra bibliotekos tipai ir kalbos ypatybės, naudojamos programos gedimams atspindėti ir spręsti. Jei norėjote suprasti, kaip nesėkmės vaizduojamos šaltinio kode, patekote į reikiamą vietą. Be „Java“ išimčių apžvalgos, aš pradėsiu nuo „Java“ kalbos funkcijų, skirtų mesti objektus, bandyti kodą, kuris gali nepavykti, gaudyti užmestus objektus ir išvalyti „Java“ kodą po to, kai bus išimtis.
Pirmoje šios pamokos pusėje sužinosite apie pagrindines kalbos ypatybes ir bibliotekos tipus, buvusius nuo „Java 1.0“. Antroje pusėje rasite pažangias galimybes, įdiegtas naujesnėse „Java“ versijose.
Atminkite, kad šios mokymo programos kodų pavyzdžiai yra suderinami su JDK 12.
atsisiųsti Gauti kodą Atsisiųskite šaltinį, pvz., programas, šioje pamokoje. Sukūrė Jeffas Friesenas, skirtas „JavaWorld“.Kokios yra „Java“ išimtys?
Gedimas įvyksta, kai įprastą „Java“ programos veikimą nutraukia netikėtas elgesys. Šis išsiskyrimas yra žinomas kaip išimtis. Pavyzdžiui, programa bando atidaryti failą, kad perskaitytų jo turinį, tačiau failo nėra. „Java“ klasifikuoja išimtis į keletą tipų, todėl apsvarstykime kiekvieną iš jų.
Patikrintos išimtys
„Java“ klasifikuoja išimtis, atsirandančias dėl išorinių veiksnių (pvz., Trūkstamo failo), kaip patikrintos išimtys. „Java“ kompiliatorius patikrina, ar tokios išimtys yra tvarkomi (pataisyti) ten, kur jie įvyksta, arba dokumentais tvarkomi kitur.
Išimčių tvarkytojai
An išimčių tvarkytojas yra kodo seka, tvarkanti išimtį. Jis klausia konteksto - tai reiškia, kad jis skaito reikšmes, išsaugotas iš kintamųjų, kurie buvo taikymo srities metu, kai įvyko išimtis, tada panaudoja tai, ko išmoko, kad atkurtų „Java“ programą įprastu elgesiu. Pavyzdžiui, išimčių tvarkytojas gali perskaityti išsaugotą failo pavadinimą ir paraginti vartotoją pakeisti trūkstamą failą.
Vykdymo (netikrintos) išimtys
Tarkime, kad programa bando sveiką skaičių padalyti iš sveiko skaičiaus 0. Šis neįmanomumas iliustruoja kitos rūšies išimtį, būtent a vykdymo laiko išimtis. Skirtingai nuo pažymėtų išimčių, vykdymo laiko išimtys paprastai kyla iš prastai parašyto šaltinio kodo, todėl jas turėtų ištaisyti programuotojas. Kadangi kompiliatorius netikrina, ar vykdymo laiko išimtys yra tvarkomos ar dokumentuojamos, kad būtų tvarkomos kitur, galite laikyti vykdymo laiko išimtį kaip nepatikrinta išimtis.
Apie vykdymo laiko išimtis
Galite modifikuoti programą, kad būtų vykdoma vykdymo laiko išimtis, tačiau geriau pataisyti šaltinio kodą. Vykdymo laiko išimtys dažnai kyla dėl neteisingų argumentų perdavimo bibliotekos metodams; turėtų būti pataisytas bagio skambinimo kodas.
Klaidos
Kai kurios išimtys yra labai rimtos, nes pakenkia programos galimybei tęsti vykdymą. Pavyzdžiui, programa bando paskirstyti atmintį iš JVM, tačiau nepakanka laisvos atminties, kad patenkintumėte užklausą. Kita rimta situacija įvyksta, kai programa bando įkelti klasės failą per „Class.forName“ ()
metodo iškvietimas, bet klasės failas yra sugadintas. Tokia išimtis yra žinoma kaip klaida. Niekada neturėtumėte pabandyti pašalinti klaidų patys, nes JVM gali nepavykti atsigauti.
Išimtys šaltinio kode
Išimtis šaltinio kode gali būti pateikiama kaip Klaidos kodas arba kaip objektas. Pristatysiu abu ir parodysiu, kodėl objektai yra pranašesni.
Klaidų kodai, palyginti su objektais
Programavimo kalbos, pvz., C, naudoja sveikąjį skaičių klaidų kodai pateikti nesėkmę ir nesėkmės priežastis - t. y. išimtis. Štai keli pavyzdžiai:
if (chdir ("C: \ temp")) printf ("Nepavyko pakeisti į temp katalogą:% d \ n", errno); FILE * fp = fopen ("C: \ temp \ foo"); if (fp == NULL) printf ("Nepavyko atidaryti foo:% d \ n", klaida);
C chdir ()
(pakeisti katalogą) funkcija grąžina sveiką skaičių: 0 sėkmės atveju arba -1, jei nesėkmė. Panašiai ir C fopen ()
(failas atidarytas) funkcija grąžina nullull rodyklė (sveikasis adresas) į a NUOTRAUKOS
sėkmės struktūra arba nulinis (0) žymeklis (pavaizduotas konstanta NULL
) dėl nesėkmės. Bet kuriuo atveju, norėdami nustatyti išimtį, kuri sukėlė gedimą, turite perskaityti visuotinę errno
kintamojo sveikojo skaičiaus klaidos kodas.
Klaidų kodai kelia keletą problemų:
- Sveikieji skaičiai yra beprasmiški; jie neapibūdina jų atstovaujamų išimčių. Pavyzdžiui, ką reiškia 6?
- Susieti kontekstą su klaidos kodu yra nepatogu. Pvz., Galbūt norėsite išvesti failo, kurio nepavyko atidaryti, pavadinimą, bet kur saugosite failo pavadinimą?
- Sveikieji skaičiai yra savavališki, o tai gali sukelti painiavą skaitant šaltinio kodą. Pavyzdžiui, nurodant
jei (! chdir ("C: \ temp"))
(!
reiškia NE) vietojjei (chdir ("C: \ temp"))
išbandyti nesėkmę yra aiškiau. Tačiau sėkmei nurodyti buvo pasirinktas 0 ir tjei (chdir ("C: \ temp"))
turi būti nurodyta išbandyti gedimą. - Klaidų kodus per lengva ignoruoti, o tai gali sukelti klaidų kodą. Pavyzdžiui, programuotojas galėtų nurodyti
chdir ("C: \ temp");
ir nepaisytijei (fp == NULL)
patikrinti. Be to, programuotojui nereikia nagrinėtierrno
. Netikrindama gedimo, programa elgiasi netaisyklingai, kai kuri nors funkcija pateikia gedimo rodiklį.
Siekdama išspręsti šias problemas, „Java“ pritaikė naują požiūrį į išimčių tvarkymą. „Java“ sistemoje objektus, apibūdinančius išimtis, deriname su mechanizmu, paremtu šių objektų mėtymu ir gaudymu. Keletas objektų, palyginti su klaidos kodu, naudojimo privalumai žymint išimtis:
- Objektą galima sukurti iš klasės su prasmingu pavadinimu. Pavyzdžiui,
FileNotFoundException
(viduje konorsjava.io
pakuotė) yra prasmingesnė nei 6. - Objektai gali išsaugoti kontekstą įvairiuose laukuose. Pvz., Objekto laukuose galite išsaugoti pranešimą, failo, kurio nepavyko atidaryti, pavadinimą, naujausią poziciją, kur nepavyko išanalizuoti, ir (arba) kitus elementus.
- Jūs nenaudojate
jei
teiginiai, kad patikrintumėte nesėkmę. Vietoj to, išimties objektai metami tvarkytojui, kuris yra atskiras nuo programos kodo. Todėl šaltinio kodas yra lengviau skaitomas ir rečiau yra klaidingas.
Metamas ir jo poklasiai
„Java“ pateikia klasių, kurios atspindi įvairias išimtis, hierarchiją. Šios klasės yra įsišaknijusios java.lang
pakuotės Metamas
klasė, kartu su ja Išimtis
, RuntimeException
ir Klaida
poklasiai.
Metamas
yra pagrindinis superklasė, kai kalbama apie išimtis. Tik objektai, sukurti iš Metamas
o jo poklasius galima mesti (ir vėliau gaudyti). Tokie objektai yra žinomi kaip mesti.
A Metamas
objektas siejamas su a išsamus pranešimas kad apibūdina išimtį. Pateikti keli konstruktoriai, įskaitant porą, aprašytą žemiau, sukuria a Metamas
objektas su išsamiu pranešimu arba be jo:
- Mesti () sukuria a
Metamas
be jokio išsamaus pranešimo. Šis konstruktorius tinka situacijoms, kai nėra konteksto. Pavyzdžiui, jūs norite žinoti tik tai, kad kaminas yra tuščias arba pilnas. - Metamas (eilutės pranešimas) sukuria a
Metamas
supranešimą
kaip išsamią žinutę. Šis pranešimas gali būti išvestas vartotojui ir (arba) užregistruotas.
Metamas
teikia Eilutė „getMessage“ ()
būdas grąžinti išsamų pranešimą. Taip pat pateikiami papildomi naudingi metodai, kuriuos pristatysiu vėliau.
Išimties klasė
Metamas
turi du tiesioginius poklasius. Vienas iš šių poklasių yra Išimtis
, kuriame aprašoma išimtis, atsirandanti dėl išorinio veiksnio (pvz., bandymo skaityti iš neegzistuojančio failo). Išimtis
deklaruoja tuos pačius konstruktorius (su vienodais parametrų sąrašais) kaip Metamas
, ir kiekvienas konstruktorius iškviečia savo Metamas
atitikmuo. Išimtis
paveldi Metamas
metodai; ji nedeklaruoja jokių naujų metodų.
„Java“ teikia daug išimčių klasių, kurios tiesiogiai perkelia poklasį Išimtis
. Štai trys pavyzdžiai:
- CloneNotSupportedException signalizuoja apie bandymą klonuoti objektą, kurio klasė neįgyvendina
Klonuojamas
sąsaja. Abi rūšys yrajava.lang
pakuotė. - IOException signalizuoja, kad įvyko kažkoks įvesties / išvesties gedimas. Šis tipas yra
java.io
pakuotė. - ParseException signalizuoja, kad analizuojant tekstą įvyko klaida. Šio tipo galite rasti
java.text
pakuotė.
Atkreipkite dėmesį, kad kiekvienas Išimtis
poklasio pavadinimas baigiasi žodžiu Išimtis
. Ši sutartis leidžia lengvai nustatyti klasės tikslą.
Paprastai priskirtumėte poklasį Išimtis
(arba vieną iš jo poklasių) su savo išimčių klasėmis (kurių pavadinimai turėtų baigtis Išimtis
). Čia yra pora pritaikytų poklasių pavyzdžių:
viešoji klasė „StackFullException“ išplečia išimtį {} public class „EmptyDirectoryException“ išplečia išimtį {private String directoryName; public EmptyDirectoryException (eilutės pranešimas, eilutės katalogo pavadinimas) {super (pranešimas); this.directoryName = katalogo pavadinimas; } public String getDirectoryName () {return directoryName; }}
Pirmajame pavyzdyje aprašoma išimčių klasė, kuriai nereikia išsamaus pranešimo. Tai numatytasis „noargument“ konstruktoriaus iškvietimas Išimtis ()
, kuris kviečia Mesti ()
.
Antrasis pavyzdys apibūdina išimčių klasę, kurios konstruktorius reikalauja išsamaus pranešimo ir tuščio katalogo pavadinimo. Konstruktorius kreipiasi Išimtis (eilutės pranešimas)
, kuris kviečia Metamas (eilutės pranešimas)
.
Objektai iš karto Išimtis
arba vienas iš jo poklasių (išskyrus RuntimeException
arba vienas iš jo poklasių) yra tikrinamos išimtys.
„RuntimeException“ klasė
Išimtis
yra tiesiogiai klasifikuojamas RuntimeException
, kuri apibūdina išimtį, kuri greičiausiai kyla dėl blogai parašyto kodo. RuntimeException
deklaruoja tuos pačius konstruktorius (su vienodais parametrų sąrašais) kaip Išimtis
, ir kiekvienas konstruktorius iškviečia savo Išimtis
atitikmuo. RuntimeException
paveldi Metamas
metodus. Ji nedeklaruoja jokių naujų metodų.
„Java“ teikia daug išimčių klasių, kurios tiesiogiai perkelia poklasį RuntimeException
. Šie pavyzdžiai yra visi java.lang
paketas:
- Aritmetinė išimtis signalizuoja apie neteisėtą aritmetinę operaciją, pvz., bandymą padalyti sveiką skaičių iš 0.
- Neteisėtas argumentas. Išimtis signalizuoja, kad metodui buvo perduotas neteisėtas ar netinkamas argumentas.
- „NullPointerException“ signalizuoja bandymą iškviesti metodą arba pasiekti egzemplioriaus lauką per nulinę nuorodą.
Objektai iš karto RuntimeException
arba vienas iš jo poklasių yra nepatikrintos išimtys.
Klaidų klasė
Metamas
kitas tiesioginis poklasis yra Klaida
, kuri apibūdina rimtą (net nenormalią) problemą, kurios nereikėtų bandyti išspręsti pagrįstai taikomai programai, pvz., atminties trūkumas, JVM kamino perpildymas ar bandymas įkelti klasę, kurios negalima rasti. Kaip Išimtis
, Klaida
deklaruoja identiškus konstruktorius Metamas
, paveldi Metamas
metodus ir nedeklaruoja jokių savo metodų.
Galite nustatyti Klaida
poklasiai iš konvencijos, kuria baigiasi jų klasių pavadinimai Klaida
. Pavyzdžiai: „OutOfMemoryError“
, „LinkageError“
ir „StackOverflowError“
. Visi trys tipai priklauso java.lang
pakuotė.
Mėtymo išimtys
C bibliotekos funkcija praneša apie išimties skambinimo kodą nustatydama visuotinę errno
kintamasis į klaidos kodą ir grąžina gedimo kodą. Priešingai, „Java“ metodas meta objektą. Žinojimas, kaip ir kada daryti išimtis, yra esminis efektyvaus „Java“ programavimo aspektas. Išmetimo išmetimas apima du pagrindinius veiksmus:
- Naudoti
mesti
pareiškimas mesti išimties objektą. - Naudoti
metimai
sąlyga informuoti kompiliatorių.
Vėlesniuose skyriuose daugiausia dėmesio bus skiriama išimčių gaudymui ir valymui po jų, bet pirmiausia sužinokime daugiau apie mėtomus daiktus.
Metimo pareiškimas
„Java“ teikia mesti
pareiškimas mesti objektą, apibūdinantį išimtį. Štai sintaksė mesti
pareiškimas:
mesti mesti;
Objektas, kurį identifikuoja mesti
yra pavyzdys Metamas
ar bet kuris jo poklasis. Tačiau jūs dažniausiai mėtote daiktus tik iš pakategorių Išimtis
arba RuntimeException
. Štai keli pavyzdžiai:
mesti naują FileNotFoundException ("nepavyksta rasti failo" + failo vardas); mesti naują „IllegalArgumentException“ („argumentas, perduotas skaičiuoti, yra mažesnis nei nulis“);
Išmetamas metamas iš dabartinio metodo į JVM, kuris patikrina, ar šis metodas yra tinkamas prižiūrėtojas. Jei nerandama, JVM išvynioja metodo skambučio kaminą, ieškodamas artimiausio skambinimo metodo, kuris galėtų apdoroti išmetimą, aprašytą išmetamuoju. Jei jis randa šį metodą, jis perduoda metimą metodo tvarkytojui, kurio kodas vykdomas, kad būtų tvarkoma išimtis. Jei nerandama metodo, kaip elgtis su išimtimi, JVM nutraukiamas tinkamu pranešimu.
Metimų sąlyga
Jūs turite informuoti kompiliatorių, kai metote pažymėtą išimtį. Atlikite tai pridėdami a metimai
metodo antraštės sąlyga. Ši sąlyga turi šią sintaksę:
metimai checkExceptionClassName (, checkExceptionClassName)*
A metimai
sąlyga susideda iš raktinio žodžio metimai
po to kableliais atskirtas klasių pavadinimų sąrašas patikrintų išimčių, išmestų iš metodo. Štai pavyzdys:
public static void main (String [] args) meta ClassNotFoundException {if (args.length! = 1) {System.err.println ("naudojimas: java ... classfile"); grįžti; } Class.forName (argumentai [0]); }
Šiame pavyzdyje bandoma įkelti klasės failą, identifikuojamą komandinės eilutės argumentu. Jei „Class.forName“ ()
negali rasti klasės failo, jis meta a java.lang.ClassNotFoundException
objektas, kuris yra pažymėta išimtis.
Patikrinta išimčių diskusija
metimai
sąlyga ir patikrintos išimtys yra prieštaringos. Daugelis kūrėjų nekenčia priversti nurodyti metimai
arba tvarkykite patikrintą (-as) išimtį (-is). Sužinokite daugiau apie tai skiltyje Ar patikrintos išimtys yra geros ar blogos? tinklaraščio straipsnis.