1. A kivételek típusai

Minden kivétel 4 típusra oszlik, amelyek valójában egymást öröklik osztályok.
Throwable
osztály
Az összes kivétel alaposztálya az Throwable
osztály. Az Throwable
osztály tartalmazza azt a kódot, amely az aktuális hívási veremet (az aktuális metódus veremnyomát) egy tömbbe írja. Kicsit később megtudjuk, mi az a veremnyom.
A dobás operátor csak olyan objektumot tud elfogadni, amely az osztályból származik Throwable
. És bár elméletileg írhat olyan kódot, mint a throw new Throwable();
, ezt általában senki sem csinálja. Az osztály fő célja, Throwable
hogy minden kivételre egyszülős osztály legyen.
Error
osztály
A következő kivételosztály az Error
osztály, amely közvetlenül örökli az Throwable
osztályt. A Java gép létrehozza az osztály objektumait Error
(és leszármazottjait), ha komoly problémák lépnek fel . Például hardverhiba, elégtelen memória stb.
Általában programozóként nem tud mit tenni olyan helyzetben, amikor egy ilyen hiba (olyan, amiért egy-t Error
kell dobni) történt a programban: ezek a hibák túl súlyosak. Nem tehet mást, mint értesíti a felhasználót, hogy a program összeomlik, és/vagy a hibáról minden ismert információt beír a programnaplóba.
Exception
osztály
A Exception
és RuntimeException
osztályok a sok metódus működése során előforduló gyakori hibákra szolgálnak. Minden dobott kivétel célja, hogy elkapja egy catch
blokk, amely tudja, hogyan kell megfelelően kezelni.
Ha egy metódus valamilyen okból nem tudja befejezni a munkáját, azonnal értesítenie kell a hívó metódust a megfelelő típusú kivétel dobásával.
Más szóval, ha egy változó egyenlő -val null
, akkor a metódus egy -et dob NullPointerException
. Ha helytelen argumentumokat adtunk át a metódusnak, akkor egy InvalidArgumentException
. Ha a metódus véletlenül nullával oszt, akkor egy ArithmeticException
.
RuntimeException
osztály
RuntimeExceptions
részhalmaza a Exceptions
. Akár azt is mondhatnánk, hogy RuntimeException
a szokásos kivételek ( ) könnyített változata Exception
– kevesebb követelmény és korlátozás vonatkozik az ilyen kivételekre
Exception
Később megtanulod, mi a különbség a és a között RuntimeException
.
2. Throws
: ellenőrzött kivételek
Minden Java-kivétel 2 kategóriába sorolható: bejelölt és nem bejelölt .
Minden kivétel, amely örökli a RuntimeException
vagy a vagy a Error
bejelöletlen kivételeket . Az összes többi ellenőrzött kivétel .
Húsz évvel az ellenőrzött kivételek bevezetése után szinte minden Java programozó ezt hibának tartja. A népszerű modern keretrendszerekben a kivételek 95%-a nincs bejelölve. A C# nyelv, amely majdnem pontosan másolta a Java-t, nem adott hozzá ellenőrzött kivételeket .
Mi a fő különbség a bejelölt és a nem ellenőrzött kivételek között?
Az ellenőrzött kivételekre további követelmények vonatkoznak . Nagyjából ezek a következők:
1. követelmény
Ha egy metódus ellenőrzött kivételt dob , akkor az aláírásában jeleznie kell a kivétel típusát . Így minden hívó metódus tudatában van annak, hogy ez az "értelmes kivétel" előfordulhat benne.
A bejelölt kivételeket a kulcsszó után a metódusparaméterekthrows
után tüntesse fel (ne használja throw
véletlenül a kulcsszót). Valahogy így néz ki:
type method (parameters) throws exception
Példa:
ellenőrzött kivétel | ellenőrizetlen kivétel |
---|---|
|
|
A jobb oldali példában a kódunk egy ellenőrizetlen kivételt dob – nincs szükség további teendőkre. A bal oldali példában a metódus ellenőrzött kivételt dob, így a throws
kulcsszó hozzáadódik a metódus aláírásához a kivétel típusával együtt.
Ha egy metódus több ellenőrzött kivételt vár , akkor mindegyiket meg kell adni a throws
kulcsszó után, vesszővel elválasztva. A sorrend nem fontos. Példa:
public void calculate(int n) throws Exception, IOException
{
if (n == 0)
throw new Exception("n is null!");
if (n == 1)
throw new IOException("n is 1");
}
2. követelmény
Ha olyan metódust hív meg, amelynek aláírása kivételeket ellenőrzött , nem hagyhatja figyelmen kívül azt a tényt, hogy kidobja azokat.
Az összes ilyen kivételt meg kell kapnia úgy, hogy catch
mindegyikhez blokkokat ad hozzá, vagy hozzá kell adnia őket athrows
metódushoz tartozó záradékhoz .
Mintha azt mondanánk: " Ezek a kivételek annyira fontosak, hogy meg kell fognunk őket. És ha nem tudjuk, hogyan kezeljük őket, akkor mindenkit értesíteni kell, aki hívja a módszerünket, hogy előfordulhatnak benne ilyen kivételek.
Példa:
Képzeld el, hogy írunk egy módszert egy emberek által lakott világ létrehozására. A kezdeti létszámot adják át érvként. Tehát kivételeket kell hozzáadnunk, ha túl kevés ember van.
Föld teremtése | jegyzet |
---|---|
|
A módszer potenciálisan két ellenőrzött kivételt dob:
|
Ez a metódushívás háromféleképpen kezelhető:
1. Ne ragadj el semmilyen kivételt
Ezt leggyakrabban akkor teszik meg, ha a módszer nem tudja, hogyan kell megfelelően kezelni a helyzetet.
Kód | jegyzet |
---|---|
|
A hívási metódus nem fogja fel a kivételeket, és tájékoztatnia kell róluk másokat: hozzáadja azokat a saját throws záradékához |
2. Fogjon meg néhány kivételt
Mi kezeljük azokat a hibákat, amelyeket kezelni tudunk. De akiket nem értünk, azokat feldobjuk a hívásmódra. Ehhez hozzá kell adnunk a nevüket a dobás záradékhoz:
Kód | jegyzet |
---|---|
|
A hívó csak egy ellenőrzött kivételt észlel – LonelyWorldException . A másik kivételt hozzá kell adni az aláírásához, a throws kulcsszó után jelezve |
3. Fogja meg az összes kivételt
Ha a metódus nem tesz kivételt a hívó metódus alól, akkor a hívó metódus mindig biztos abban, hogy minden jól működött. És nem tud semmilyen intézkedést tenni a kivételes helyzetek megoldására.
Kód | jegyzet |
---|---|
|
Ez a módszer minden kivételt megragad. A hívó biztos abban, hogy minden rendben ment. |
3. Burkolási kivételek
Az ellenőrzött kivételek elméletben menőnek tűntek, de a gyakorlatban óriási csalódásnak bizonyultak.
Tegyük fel, hogy van egy rendkívül népszerű módszer a projektjében. A programodban több száz helyről hívják. És úgy dönt, hogy hozzáad egy új ellenőrzött kivételt. És könnyen lehet, hogy ez az ellenőrzött kivétel valóban fontos és annyira különleges, hogy csak a main()
metódus tudja, mit kell tenni, ha elkapják.
Ez azt jelenti, hogy hozzá kell adnia a bejelölt kivételt throws
minden olyan metódus záradékához, amely a szupernépszerű metódusát hívja meg . Valamint throws
az összes olyan metódus záradékában, amely ezeket a metódusokat hívja. És azokról a módszerekről, amelyek ezeket a módszereket hívják.
Ennek eredményeként throws
a projektben a metódusok felének záradékai új ellenőrzött kivételt kapnak. És természetesen a projektjét tesztek fedik le, és most a tesztek nem fordítódnak le. És most szerkesztened kell a dobások záradékait is a tesztekben.
Ezután az összes kódot (a több száz fájlban lévő összes változást) más programozóknak át kell nézniük. És ezen a ponton feltesszük magunknak a kérdést, hogy miért hajtottunk végre annyi véres változtatást a projekten? Munkanap(ok) és hibás tesztek – mindez csak egy ellenőrzött kivétel hozzáadásának kedvéért ?
És természetesen továbbra is vannak problémák az örökléssel és a módszer felülbírálásával kapcsolatban. Az ellenőrzött kivételekből származó problémák sokkal nagyobbak, mint a haszon. A lényeg az, hogy ma már kevesen szeretik és kevesen használják.
Azonban még mindig sok olyan kód van (beleértve a szabványos Java könyvtári kódot is), amely ezeket az ellenőrzött kivételeket tartalmazza. Mi a teendő velük? Nem hagyhatjuk figyelmen kívül őket, és nem tudjuk, hogyan kezeljük őket.
A Java programozók azt javasolták, hogy az ellenőrzött kivételeket csomagolja be RuntimeException
. Más szóval, fogja meg az összes ellenőrzött kivételt, majd hozzon létre nem ellenőrzött kivételeket (például RuntimeException
), és dobja el őket. Ez valahogy így néz ki:
try
{
// Code where a checked exception might occur
}
catch(Exception exp)
{
throw new RuntimeException(exp);
}
Nem túl szép megoldás, de nincs itt semmi bűnöző: a kivételt egyszerűen egy RuntimeException
.
Ha szükséges, onnan könnyen visszakeresheti. Példa:
Kód | jegyzet |
---|---|
|
A kivétel tárolása az RuntimeException objektumon belül. A cause változó esetleg null Meghatározza a típusát, és konvertálja ellenőrzött kivételtípussá. |
4. Több kivétel elkapása
A programozók nagyon utálják a kód megkettőzését. Még egy megfelelő fejlesztési elvet is kitaláltak: Ne ismételd magad (SZÁRAZ) . A kivételek kezelésekor azonban gyakran előfordulnak olyan esetek, amikor egy blokkot több azonos kódú blokk try
követ .catch
Vagy lehet 3 catch
blokk ugyanazzal a kóddal és további 2 catch
blokk más azonos kóddal. Ez egy szokásos helyzet, amikor a projekt felelősen kezeli a kivételeket.
A 7-es verziótól kezdődően a Java nyelv több típusú kivételt is megadhat egyetlen blokkban catch
. Valahogy így néz ki:
try
{
// Code where an exception might occur
}
catch (ExceptionType1 | ExceptionType2 | ExceptionType3 name)
{
// Exception handling code
}
Annyi blokkja lehet, amennyit catch
csak akar. Egyetlen catch
blokk azonban nem határozhat meg olyan kivételeket, amelyek öröklik egymást. Más szóval, nem írhatod a catch ( Exception
| RuntimeException
e) kifejezést, mert az RuntimeException
osztály örökli a -t Exception
.
5. Egyéni kivételek
Mindig létrehozhat saját kivételosztályt. Egyszerűen létrehoz egy osztályt, amely örökli az RuntimeException
osztályt. Valahogy így fog kinézni:
class ClassName extends RuntimeException
{
}
Megbeszéljük a részleteket, miközben megtanulja az OOP-t, az öröklődést, a konstruktorokat és a metódusok felülbírálását.
Ha azonban csak egy ilyen egyszerű osztályod van (teljesen kód nélkül), akkor is dobhatsz kivételeket az alapján:
Kód | jegyzet |
---|---|
|
Dobj egy ellenőrizetlen MyException . |
A Java Multithreading küldetés során mélyen elmerülünk a saját egyéni kivételeinkkel való munka során.
GO TO FULL VERSION