Programavimas

„Java“ išimtys, 2 dalis: Išplėstinės funkcijos ir tipai

JDK 1.0 pristatė kalbos ypatybių ir bibliotekų tipų sistemą, skirtą tvarkyti išimtys, kurie skiriasi nuo numatomos programos elgsenos. Pirmoji šios mokymo programos pusė apėmė pagrindines „Java“ išimčių tvarkymo galimybes. Šioje antrojoje pusėje pristatomos pažangesnės „JDK 1.0“ ir jos tęsėjų teikiamos galimybės: „JDK 1.4“, „JDK 7“ ir „JDK 9.“. Sužinokite, kaip numatyti ir valdyti „Java“ programų išimtis naudojant pažangias funkcijas, tokias kaip kamino pėdsakai, priežastys ir išimčių grandinė, pabandykite - su ištekliais, daugkartinis laimikis, paskutinis metimas ir ėjimas rietuvėmis.

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“.

Išimčių tvarkymas JDK 1.0 ir 1.4 versijose: kamino pėdsakai

Kiekvienas JVM siūlas (vykdymo kelias) siejamas su a kamino kuri sukurta, kai sukuriama gija. Ši duomenų struktūra yra suskirstyta į rėmai, kurios yra duomenų struktūros, susijusios su metodo iškvietimais. Dėl šios priežasties kiekvienos gijos krūva dažnai vadinama a metodo skambučio kamino.

Kiekvieną kartą, kai iškviečiamas metodas, sukuriamas naujas rėmas. Kiekviename kadre saugomi vietiniai kintamieji, parametrų kintamieji (kuriuose yra metodui perduoti argumentai), informacija, skirta grįžti prie iškvietimo metodo, vieta grąžinimo vertei saugoti, informacija, naudinga siunčiant išimtį ir pan.

A kamino pėdsakas (taip pat žinomas kaip a kamino atgalinis pėdsakas) yra aktyvių kamino rėmelių ataskaita tam tikru momentu gijos vykdymo metu. „Java“ Metamas klasėje ( java.lang paketas) pateikia metodus, kaip atspausdinti kamino pėdsaką, užpildyti kamino pėdsaką ir pasiekti rietuvės pėdsako elementus.

Kaminų pėdsakų spausdinimas

Kai mesti pareiškimas meta mesti, pirmiausia ieško tinkamo pagauti blokuoti vykdymo metodą. Jei nerandama, jis išsisuka metodo skambučio kaminą ieškodamas artimiausio pagauti blokas, kuris gali tvarkyti išimtį. Jei nerandama, JVM nutraukiamas tinkamu pranešimu. Apsvarstykite 1 sąrašą.

1 sąrašas. „PrintStackTraceDemo.java“ (1 versija)

importuoti java.io.IOException; public class PrintStackTraceDemo {public static void main (String [] args) meta IOException {meta nauja IOException (); }}

Išvardijus 1 sugalvotą pavyzdį, sukuriamas a java.io.IOException objektą ir išmeta šį objektą iš pagrindinis () metodas. Nes pagrindinis () netvarko šio metamo ir todėl pagrindinis () yra aukščiausio lygio metodas, JVM nutraukiamas tinkamu pranešimu. Šioje programoje pamatysite šį pranešimą:

Išimtis temoje „main“ java.io.IOException at PrintStackTraceDemo.main (PrintStackTraceDemo.java:7)

JVM išsiunčia šį pranešimą skambindamas Metamas's void printStackTrace () metodas, kuris išspausdina kamino pėdsaką iškvietimui Metamas objektas standartiniame klaidų sraute. Pirmoje eilutėje parodomas išmetamųjų iškvietimo rezultatas toString () metodas. Kitoje eilutėje rodomi anksčiau įrašyti duomenys „fillInStackTrace“ () (aptarta netrukus).

Papildomi spausdinimo kamino atsekimo metodai

Metamasyra perkrautas void printStackTrace („PrintStream ps“) ir void printStackTrace („PrintWriter pw“) metodai pateikia rietuvės pėdsaką nurodytam srautui ar rašytojui.

Kamino pėdsakas atskleidžia šaltinio failą ir eilutės numerį, kur buvo sukurtas metimas. Šiuo atveju jis buvo sukurtas 7 eilutėje „PrintStackTrace.java“ šaltinio failas.

Galite kreiptis „printStackTrace“ () tiesiogiai, paprastai iš a pagauti blokuoti. Pvz., Apsvarstykite antrąją „PrintStackTraceDemo“ taikymas.

2 sąrašas. „PrintStackTraceDemo.java“ (2 versija)

importuoti java.io.IOException; public class PrintStackTraceDemo {public static void main (String [] args) meta IOException {try {a (); } gaudyti (IOException ioe) {ioe.printStackTrace (); }} static void a () išmeta IOException {b (); } static void b () išmeta IOException {meta naują IOException (); }}

2 sąrašas rodo, kad a pagrindinis () metodas, kuris iškviečia metodą a (), kuris iškviečia metodą b (). Metodas b () meta an IOException objektas JVM, kuris atriša metodo iškvietos kaminą, kol suranda pagrindinis ()'s pagauti blokas, kuris gali tvarkyti išimtį. Išimtis sprendžiama iškviečiant „printStackTrace“ () ant užmetamo. Šis metodas sukuria tokią išvestį:

java.io.IOException at PrintStackTraceDemo.b (PrintStackTraceDemo.java:24) at PrintStackTraceDemo.a (PrintStackTraceDemo.java:19) at PrintStackTraceDemo.main (PrintStackTraceDemo.java:9)

„printStackTrace“ () neišleidžia gijos pavadinimo. Užuot tai iškėlęs toString () užmetamą, kad būtų galima grąžinti visiškai kvalifikuotą klasės vardą (java.io.IOException), kuris išvedamas pirmoje eilutėje. Tada ji pateikia metodo skambučio hierarchiją: naujausią metodą (b ()) yra viršuje ir pagrindinis () yra apačioje.

Kokią eilutę identifikuoja kamino pėdsakas?

Kamino pėdsakas identifikuoja liniją, kurioje sukuriamas užmetamas. Jis nenustato linijos, kur mėtomas išmetamas (via mesti), nebent užmetamas būtų mėtomas toje pačioje eilutėje, kur jis sukurtas.

Kamino pėdsako užpildymas

Metamas pareiškia a Metamas užpildymasInStackTrace () metodas, kuris užpildo vykdymo kamino pėdsakus. Kreipiantis Metamas objektas, jis įrašo informaciją apie dabartinę siūlų rietuvių rėmelių būseną. Apsvarstykite 3 sąrašą.

3 sąrašas. „FillInStackTraceDemo.java“ (1 versija)

importuoti java.io.IOException; public class FillInStackTraceDemo {public static void main (String [] args) meta IOException {try {a (); } gaudyti (IOException ioe) {ioe.printStackTrace (); System.out.println (); mesti (IOException) ioe.fillInStackTrace (); }} static void a () išmeta IOException {b (); } static void b () išmeta IOException {meta naują IOException (); }}

Pagrindinis skirtumas tarp 3 ir 2 sąrašų yra pagauti blokuoti mesti (IOException) ioe.fillInStackTrace (); pareiškimas. Šis teiginys pakeičia ioekamino pėdsakas, po kurio užmetamas metamas iš naujo. Turėtumėte stebėti šį rezultatą:

java.io.IOException „FillInStackTraceDemo.b“ („FillInStackTraceDemo.java:26“) „FillInStackTraceDemo.a“ („FillInStackTraceDemo.java:21“) „FillInStackTraceDemo.main“ („FillInStackTrack“ „FillInStackTraceDemo.main“ („FillInStackTraceDemo.java:15“)

Užuot pakartojus pradinį kamino pėdsaką, kuris identifikuoja vietą, kurioje IOException objektas buvo sukurtas, antrasis kamino pėdsakas atskleidžia „ioe.fillInStackTrace“ ().

Metami konstruktoriai ir „fillInStackTrace“ ()

Kiekvienas iš Metamasremiasi konstruktoriai fillInStackTrace (). Tačiau šis konstruktorius (pristatytas JDK 7) nepraleis šio metodo, kai praeisite melagingas į writeableStackTrace:

„Throwable“ (eilutės pranešimas, „Throwable“ priežastis, „Boolean enableSuppression“, „Boolean writableStackTrace“)

fillInStackTrace () iškviečia savąjį metodą, kuris eina žemyn dabartinės gijos metodo iškvietimo kamino, kad sukurtumėte kamino pėdsaką. Šis pasivaikščiojimas yra brangus ir gali turėti įtakos našumui, jei jis vyksta per dažnai.

Jei susiduriate su situacija (galbūt susijusi su įdėtuoju įrenginiu), kai našumas yra labai svarbus, galite išvengti rietuvės pėdsakų kūrimo nepaisydami „fillInStackTrace“ (). Peržiūrėkite 4 sąrašą.

4 sąrašas. „FillInStackTraceDemo.java“ (2 versija)

{public static void main (String [] args) meta NoStackTraceException {try {a (); } gaudyti (NoStackTraceException nste) {nste.printStackTrace (); }} static void a () išmeta NoStackTraceException {b (); } static void b () throws NoStackTraceException {throws new NoStackTraceException (); }} klasė „NoStackTraceException“ išplečia išimtį {@Override public synchronized Throwable fillInStackTrace () {return this; }}

Pateikiamas 4 sąrašas „NoStackTraceException“. Šis pasirinktinai patikrintas išimčių klasės nepaisymas fillInStackTrace () Grįžti tai - nuoroda į kreipimąsi Metamas. Ši programa sukuria tokį išėjimą:

„NoStackTraceException“

Pakomentuokite svarbesnį dalyką „fillInStackTrace“ () metodą ir stebėsite šį rezultatą:

„NoStackTraceException“ adresu FillInStackTraceDemo.b (FillInStackTraceDemo.java:22) ne FillInStackTraceDemo.a (FillInStackTraceDemo.java:17) FillInStackTraceDemo.main (FillInStackTrja

Prieiga prie kamino pėdsakų elementų

Kartais turėsite pasiekti kamino pėdsakų elementus, kad gautumėte išsamią informaciją, reikalingą registravimui, išteklių nuotėkio šaltinio nustatymui ir kitiems tikslams. „printStackTrace“ () ir „fillInStackTrace“ () metodai nepalaiko šios užduoties, tačiau pristatytas JDK 1.4 java.lang.StackTraceElement ir jo metodai šiam tikslui.

java.lang.StackTraceElement klasėje aprašomas elementas, vaizduojantis kamino rėmą kamino pėdsakuose. Jo metodai gali būti naudojami grąžinti visiškai kvalifikuotą klasės pavadinimą, kuriame yra vykdymo taškas, kurį vaizduoja šis kamino mikroelementas, kartu su kita naudinga informacija. Čia pateikiami pagrindiniai metodai:

  • Eilutė „getClassName“ () grąžina visiškai kvalifikuotą klasės pavadinimą, kuriame yra vykdymo taškas, kurį vaizduoja šis kamino sekimo elementas.
  • Eilutė „getFileName“ () grąžina šaltinio failo, kuriame yra vykdymo taškas, kurį žymi šis kamino pėdsakų elementas, pavadinimą.
  • int getLineNumber () grąžina šaltinio eilutės, kurioje yra vykdymo taškas, kurį žymi šis kamino pėdsakų elementas, eilutės numerį.
  • Eilutė „getMethodName“ () grąžina metodo pavadinimą, kuriame yra vykdymo taškas, kurį vaizduoja šis kamino sekimo elementas.
  • loginis isNativeMethod () grįžta tiesa kai metodas, kuriame yra vykdymo taškas, kurį vaizduoja šis kamino mikroelementas, yra įprastas metodas.

JDK 1.4 taip pat pristatė „StackTraceElement“ [] getStackTrace () metodas java.lang.Twread ir Metamas klasės. Šis metodas atitinkamai grąžina rietuvės mikroelementų masyvą, žymintį iškviečiamo gijos kamino iškrovimą ir suteikia programinę prieigą prie rietuvės pėdsakų informacijos, išspausdintos „printStackTrace“ ().

5 sąrašas rodo „StackTraceElement“ ir „getStackTrace“ ().

5 sąrašas. „StackTraceElementDemo.java“ (1 versija)

importuoti java.io.IOException; public class StackTraceElementDemo {public static void main (String [] args) meta IOException {try {a (); } gaudyti (IOException ioe) {StackTraceElement [] stackTrace = ioe.getStackTrace (); for (int i = 0; i <stackTrace.length; i ++) {System.err.println ("Išimtis, išmesta iš" + stackTrace [i] .getMethodName () + "klasėje" + stackTrace [i] .getClassName () + "on line" + stackTrace [i] .getLineNumber () + "failo" + stackTrace [i] .getFileName ()); System.err.println (); }}} static void a () išmeta IOException {b (); } static void b () išmeta IOException {meta naują IOException (); }}

Paleidę šią programą pastebėsite šį išvestį:

Išimtis iš „St“ klasės „StackTraceElementDemo“ failo „StackTraceElementDemo.java“ 33 eilutėje. Išimtis iš „StackTraceElementDemo“ klasės eilutės failo „StackTraceElementDemo.java“ 28 eilutėje. Išimtis, išmetama iš „StackTraceElementDemo“ klasės pagrindinės eilutės.

Galiausiai JDK 1.4 pristatė setStackTrace () metodas Metamas. Šis metodas yra skirtas naudoti nuotolinių procedūrų iškvietimo (RPC) sistemose ir kitose pažangiose sistemose, leidžiant klientui nepaisyti numatytojo kamino pėdsako, kurį sukuria „fillInStackTrace“ () kai sukonstruojamas metamas.

Anksčiau parodžiau, kaip nepaisyti „fillInStackTrace“ () kad nebūtų pastatytas kamino pėdsakas. Vietoj to galite įdiegti naują kamino pėdsaką naudodami „StackTraceElement“ ir setStackTrace (). Sukurkite masyvą „StackTraceElement“ objektai inicializuoti per šį konstruktorių ir perduoti šį masyvą setStackTrace ():

„StackTraceElement“ (eilutė deklaruojanti klasė, eilutės metodo pavadinimas, eilutės failo pavadinimas, int eilutės numeris)

6 sąrašas rodo „StackTraceElement“ ir setStackTrace ().