1. A kivételek típusai

Minden kivétel 4 típusra oszlik, amelyek valójában egymást öröklik osztályok.

Throwableosztály

Az összes kivétel alaposztálya az Throwableosztály. Az Throwableosztá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, Throwablehogy minden kivételre egyszülős osztály legyen.

Errorosztály

A következő kivételosztály az Errorosztály, amely közvetlenül örökli az Throwableosztá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 Errorkell 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.

Exceptionosztály

A Exceptionés RuntimeExceptionosztá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 catchblokk, 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.

RuntimeExceptionosztály

RuntimeExceptionsrészhalmaza a Exceptions. Akár azt is mondhatnánk, hogy RuntimeExceptiona szokásos kivételek ( ) könnyített változata Exception– kevesebb követelmény és korlátozás vonatkozik az ilyen kivételekre

ExceptionKé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 RuntimeExceptionvagy a vagy a Errorbejelöletlen kivételeket . Az összes többi ellenőrzött kivétel .

Fontos!

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 throwvé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
public void calculate(int n) throws Exception
{
   if (n == 0)
      throw new Exception("n is null!");
}
public void calculate(n)
{
   if (n == 0)
      throw new RuntimeException("n is null!");
}

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 throwskulcsszó 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 throwskulcsszó 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 catchmindegyikhez 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
public void createWorld(int n) throws EmptyWorldException, LonelyWorldException
{
   if (n == 0)
      throw new EmptyWorldException("There are no people!");
   if (n == 1)
      throw new LonelyWorldException ("There aren't enough people!");
   System.out.println("A wonderful world was created. Population: " + n);
}
A módszer potenciálisan két ellenőrzött kivételt dob:

  • EmptyWorldException
  • LonelyWorldException

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
public void createPopulatedWorld(int population)
throws EmptyWorldException, LonelyWorldException
{
   createWorld(population);
}
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 throwszá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
public void createNonEmptyWorld(int population)
throws EmptyWorldException
{
   try
   {
      createWorld(population);
   }
   catch (LonelyWorldException e)
   {
      e.printStackTrace();
   }
}
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 throwskulcsszó 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
public void createAnyWorld(int population)
{
   try
   {
      createWorld(population);
   }
   catch (LonelyWorldException e)
   {
      e.printStackTrace();
   }
   catch (EmptyWorldException e)
   {
      e.printStackTrace();
   }
}
Ez a módszer minden kivételt megragad. A hívó biztos abban, hogy minden rendben ment.


3. 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 – DRY : Don't Repeat Yourself. A kivételek kezelésekor azonban gyakran előfordulnak olyan esetek, amikor egy blokkot több azonos kódú blokk trykövet .catch

Vagy lehet 3 catchblokk ugyanazzal a kóddal és további 2 catchblokk 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 nyelvben lehetőség nyílt többféle kivétel megadására egyetlen blokkban catch. Nagyjából így néz ki:

try
{
   // Code where an exception might occur
}
catch (ExceptionType1 | ExceptionType2 | ExceptionType3 name)
{
   // Exception handling code
}

Annyi blokkja lehet, amennyit catchcsak akar. Egyetlen catchblokk azonban nem határozhat meg olyan kivételeket, amelyek öröklik egymást. Más szóval, nem írhatod a catch ( Exception| RuntimeExceptione) kifejezést, mert az RuntimeExceptionosztály örökli a -t Exception.