Saját kivétel készítése

2019. május 26.

Szeretem a fura címeket… a cikk címéből nem biztos, hogy egy teljesen random ember számára ez bármilyen értelemmel is bírna, de itt és most arról lesz szó, hogy Java nyelven hogyan is kell saját Exceptiont létrehozni. Szóval vágjunk is bele! 🙂

Mik a kivételek?

Egy rövid kis bevezetőként, mik azok a kivételek és miért is dobáljuk őket. Ugye a program futásakor, ha bármiféle kivételes esemény történik, ami a normál működéstől eltér, akkor az eseményről létrejön egy objektum, ami a kivételes esemény típusát, körülményeit foglalja magába, és ez ez objektum átadásra kerül a rendszernek. Nos az objektum a kivétel, és ezt “dobják”. 😛

Ismerünk mindenféle kivételeket: IllegalArgumentException, IndexOutOfBoundsException, IOException, stb. Azt kell még tudni, hogy ezek hierarchiába szerveződnek. Itt egy jó kis összefoglaló ábra hozzájuk (https://www.javamadesoeasy.com):

Keressük az indokot!

Tudjuk, hogy van kismillió meg egy kivétel, amelyet a nyelv alapkönyvtárai biztosítanak, így teljesen jogosan merül fel az, hogy minek is csináljunk saját kivételt? Nem lenne elég csak megkeresni azt, ami a legjobban illik az adott szituációhoz?

Nos… egy saját kivétel megadja a lehetőségét annak, hogy olyan specifikus adatokat is tárolhassunk, iletve saját logikát adhassunk hozzá kivétel esetén, ami nem része egy sztenderd Java-s kivételnek. Gondolok itt például olyan dolgokra, mint hogy egy hibakódot rendeljünk az eseményhez, vagy utility metódusokat írjunk, ami a kivétel megjelenítésén módosít. Persze akár az is opció, hogy minden, a rendszerben keletkezett kivétel legyen rendszer-specifikus, hogy a sok rendszer között meg lehessen különböztetni, vagy hogy a fejlesztők életét könnyítse meg, ha a hiba okát kell keresni, stb.

Nagyon fontos, hogy ha nem tudunk ilyen plusz értékeket felsorakoztatni, akkor érdemes inkább az alap kivételek között keresni egyet, ami a legjobban megfelel az adott eseménynek.

Hogyan csináljunk saját kivételt?

Most már tudjuk az indokokat és elhatároztuk, hogy csinálunk egy saját kivételt.

Származtatás

Ellenőrzött kivétel esetén az Exception, futásidejű kivétel esetén pedig a RuntimeException osztályokból kell származtatnunk.

Kiemelten fontos az is, hogy kövessük a nevezéktant, azaz minden létrehozott kivétel Exception végű legyen.

public class CustomBusinessException extends RuntimeException { 
}

Konstruktorok

Ami még feladat, hogy írjunk olyan konstruktorokat, amelyek használhatóvá teszik a kivételt.

Mindig szokott lenni egy üzenet, amit utána továbbadhatunk az ősnek.

public class CustomBusinessException extends RuntimeException { 
    public CustomBusinessException(String message) {
        super(message);
    }
}

Ugyanígy nagyon fontos, hogy olyan konstruktor is legyen, amelyen keresztül átadásra kerüljön a gyökérok, a kiváltó alapkivétel is. Ezt egy Throwable típusú paraméter átadásával érhetjük el, amit továbbadunk az ősnek.

public class CustomBusinessException extends RuntimeException { 
     public CustomBusinessException(String message) {
         super(message);
     }
 
     public CustomBusinessException(String message, Throwable cause) {
         super(message, cause);
     } 
 }

Saját paraméterek

Az egyik értékteremtő része a saját kivételnek az, hogy plusz adattagokat tud tárolni. Ezek értékét szintén a konstruktoron keresztül tudjuk megkapni, és ‘helyben’ kell tárolni, épp ezért gettert is érdemes hozzá felvenni, hogy később kiolvasható legyen. (Ezt persze szintén lehet Lombok segítségével a @Getter annotációval)

public class CustomBusinessException extends RuntimeException { 

     private final int errorCode;

     public CustomBusinessException(String message) {
         super(message);
     }
 
     public CustomBusinessException(String message, Throwable cause) {
         super(message, cause);
     } 

     public CustomBusinessException(String message, Throwable cause, int errorCode) {
         super(message, cause);
         this.errorCode = errorCode;
     }

     public int getErrorCode() {
         return errorCode;
     }
 }

Itt azt emelném még ki, hogy saját adattag esetén ügyeljünk arra, hogy immutable legyen. Mert az egésznek a lényege az, hogy megőrizze a kivétel időpontjában fennálló állapotot, körülményeket, hogy még esélyt se adjunk arra, hogy valahogyan ez megváltozásra kerüljön. Még Sonar rule is van hozzá, szóval ha véletlenül elfelejtenénk, akkor is szólni fog az RSPEC-1165 azonosítójú szabály betartására. 🙂

Dokumentáció!!!

Bár általános dolog, hogy mindent dokumentálni kell, azért mégis külön kiemelném, hogy semmiképpen ne legyen elfelejtve. Hisz ha már korábban bármikor is találkozunk olyan kivétellel, amihez nem volt dokumentáció, akkor tudható, hogy a nem dokumentált kivételeket nehéz jól használni. 🙂

Épp ezért amit mindeképpen érdemes beleírni, az az, hogy általánosságban mire is használatos, mi a jelentése, illetve, hogy milyen esetekben fordulhat elő konkrétan.

+1 Típusosság

Bár néha nagyon jól jönne, de sajnos nem lehet típusos kivételeket létrehozni. Ennek okát, és az egész problémakört nagyon jól összeszedik ennél a SO kérdésnél: Why doesn’t Java allow generic subclasses of Throwable?

Összefoglalás

Csak akkor hozzunk létre kivételt, ha az tényleg valamilyen plusz értéket tud képviselni. Adjuk át a gyökérokot is, és ne felejtsük el a kivételt dokumentálni!

Ezen tudással felvértezve pedig már csak dobálni kell őket! Jahh és némelyiket elkapni sem árt… 😉

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük