Erindite tüübid
Sissejuhatus
Javas jagunevad erindid kahe leeri: checked ehk kontrollitud erindid ja unchecked ehk kontrollimata erindid. Nende erinevus seisneb selles, kas kompilaator nõuab arendajalt nendega tegelemist või mitte.
Exception
├── IOException — checked
├── SQLException — checked
├── YourCustomException — checked (if extends Exception directly)
└── RuntimeException
├── NullPointerException — unchecked
├── IllegalArgumentException — unchecked
└── YourCustomRuntimeException — unchecked (if extends RuntimeException)
Kontrollitud erindid (checked exceptions)
Kontrollitud erind on erind, millega arendaja peab eraldi tegelema.
Erindeid lahendatakse kas try-catch plokiga või meetodi päises throws deklareerides.
Viimane delegeerib erindiga tegelemise järgmisele meetodile ehk throws ei tähenda seda, et enam antud erindiga tegelema ei pea.
Kontrollitud erinditega mitte tegelemine lõppeb kompileerimisveaga:
public void readFile(String path) {
FileReader reader = new FileReader(path); // Error: unhandled IOException
}
Antud juhul kompilaator üritab märku anda, et see meetod võib lõppeda veaga, mis ei tulene koodist endast. Nagu varem mainitud, siis seda saab lahendada kahel viisil:
// Option 1: catch and handle it
public void readFile(String path) {
try {
FileReader reader = new FileReader(path);
// ...
} catch (IOException e) {
System.out.println("File not found: " + e.getMessage());
}
}
// Option 2: declare it with throws
public void readFile(String path) throws IOException {
FileReader reader = new FileReader(path);
// ...
}
Viimase viisi puhul peab iga meetod, mis kutsub readFile() meetodit, erindiga tegelema.
Kontrollitud erindid pärinevad Exception klassist (välja arvatud RuntimeException ja selle alamklassid), näiteks:
public class InsufficientFundsException extends Exception {
public InsufficientFundsException(String message) {
super(message);
}
}
Kontrollimata erindid (unchecked exceptions)
Kontrollimata erindi puhul ei pea erindit eraldi kinni püüdma või deklareerima. Kompilaator ei nõua nende käsitlemist.
Kõik kontrollimata erindid on RuntimeException alamklassid ning need tüüpiliselt tähistavad vigu koodis ehk olukordi mis ei tohiks tekkida, kui kood on kirjutatud/kasutatud korrektselt.
Näiteks:
public void withdraw(double amount) {
if (amount < 0) {
throw new IllegalArgumentException("Amount cannot be negative");
// No throws declaration needed
}
}
Kontrollimata erindeid ei pea meetodi päises throws abil deklareerima.
Näiteid kontrollimata erinditest Javas endas:
| Erind | Tüüpiline tekkepõhjus |
|---|---|
NullPointerException | Meetodi kasutamine null-viida peal |
IllegalArgumentException | Meetodile antud andmed olid vigased |
IllegalStateException | Objekti olek operatsiooni läbi viimiseks oli väär |
ArrayIndexOutOfBoundsException | Massiivist elemendi võtmine mitteeksisteerivalt indeksilt |
ClassCastException | Illegaalne downcast |
ArithmeticException | Nulliga jagamine |
Millal millist kasutada
Reeglina:
- Kasuta kontrollitud erindit juhul, kui veast on võimalik mõistlikult taastuda. Näiteks faili ei leita üles, võrguühendus aegub või välisest allikast saadud andmed on vigased. Need on olukorrad, mis ei ole programmi otsese kontrolli all.
- Kasuta kontrollimata erindit, kui viga on põhjustatud koodi valest kasutamisest - vale argument, vigane olek või väärkasutus. Need on programmeerimisvead, mille peaks seda meetodit kasutav kood korda tegema, mitte kinni püüdma.
Kui pole selge, kumba kasutada, eelistatakse üldiselt kontrollimata erindeid. Need sobivad paremini programmeerimisvigade tähistamiseks ning ei sunni kutsuvat koodi eraldi veakäsitlust lisama. Kontrollitud erindid sunnivad arendajat igal korral tegelema veakäsitlusega, mis teeb koodi raskemini loetavamaks. Kontrollitud erindit peaks kasutama ainult juhul, kui viga tuleb ilmtingimata käsitleda.
Paljud kaasaegsed Java raamistikud, nagu Spring, eelistavad kontrollimata erindeid ning kasutavad neid oma sisemises veakäsitluses peaaegu eranditult. Selline lähenemine muudab koodi puhtamaks, kuna veakäsitlus ei leki äriloogikasse.