Unntak

try {
    Scanner scan = new Scanner(new File("filnavn"));
    String navn = scan.next();
    String yrke = scan.next();

} catch (FileNotFoundException e) {
    System.out.println("Filen filnavn ble ikke funnet!");
    System.exit(-1);
} catch (NoSuchElementException e) {
    System.err.println("Filen er ikke komplett!");
    e.printStackTrace();
    System.exit(-1);
}

Hva er unntak?

Exception object

Throwing an exception

Exception handler

Eksempel på unntak i metoder

Et eksempel på en kallstakk

Vi får et unntak og må lete i kallstakken etter en unntaksbehandler

Hvordan oppdage og behandle unntak?

try

catch

finally

Prøv å kjøre kode

Fang et unntak hvis det kastes av koden i try

Uansett hva som skjer over kjøres denne koden

try {
    code
}
catch and finally blocks . . .

Eksempel på try-blokk (1)

NB!

Kode i catch og finally kan også kaste exception!

Dette kalles chained exceptions.

private List<Integer> list;
private static final int SIZE = 10;

public void writeList() {
    PrintWriter out = null;
    try {
        System.out.println("Entered try statement");
        out = new PrintWriter(new FileWriter("OutFile.txt"));
        for (int i = 0; i < SIZE; i++) {
            out.println("Value at: " + i + " = " + list.get(i));
        }
    }
    catch and finally blocks  . . .
}

Eksempel på try-blokk (2)

try {
    code som kaster IndexOutOfBoundsException og IOException
} catch (IndexOutOfBoundsException e) {
    System.err.println("IndexOutOfBoundsException: " + e.getMessage());
} catch (IOException e) {
    System.err.println("Caught IOException: " + e.getMessage());
}

Eksempel på catch

Man kan ha en eller flere catch-blokker. Hvis man vil fange flere tilfeller på en gang må man fange superklassen.

finally {
    if (out != null) { 
        System.out.println("Closing PrintWriter");
        out.close(); 
    } else { 
        System.out.println("PrintWriter not open");
    } 
}

Eksempel på finally

Kan brukes til for eksempel å lukke en stream (PrintWriter, Scanner o.l)

Kjøres uansett hva som skjer i try-blokken

static String readFirstLineFromFile(String path) throws IOException {
    try (BufferedReader br =
                   new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}

Bonus:

Try-with-resources

Lukker automatisk ressurser som har blitt åpnet, når try-blokken avluttes

Kjøres uansett hva som skjer i try-blokken

Fungerer kun med objekter som implementerer java.lang.AutoCloseable

public void writeList() {
    PrintWriter out = null;

    try {
        System.out.println("Entering" + " try statement");

        out = new PrintWriter(new FileWriter("OutFile.txt"));
        for (int i = 0; i < SIZE; i++) {
            out.println("Value at: " + i + " = " + list.get(i));
        }
    } catch (IndexOutOfBoundsException e) {
        System.err.println("Caught IndexOutOfBoundsException: "
                           +  e.getMessage());
                                 
    } catch (IOException e) {
        System.err.println("Caught IOException: " +  e.getMessage());
                                 
    } finally {
        if (out != null) {
            System.out.println("Closing PrintWriter");
            out.close();
        } 
        else {
            System.out.println("PrintWriter not open");
        }
    }
}

Hvordan kaste unntak?

throw

Throwable

throws

Brukes til å generere (kaste) et nytt unntak.

Alle unntak er subklasser av klassen Throwable. Dette gjør at vi kan si throw (new) Exception.

Istedet for å behandle et unntak kan man sende unntaket videre ut til neste steg i kallstakken. Da må metoden si throws Exception.

Eksempel på bruk av throw

Uansett hvor et unntak kommer fra blir det alltid kastet med throw

public Object pop() {
    Object obj;

    if (size == 0) {
        throw new EmptyStackException();
    }

    obj = objectAt(size - 1);
    setObjectAt(size - 1, null);
    size--;
    return obj;
}

Mer om throw

throw krever bare et argument: et throwable objekt

Error, Exception og RuntimeException arver alle fra Throwable

public void writeList() {
    PrintWriter out = new PrintWriter(new FileWriter("OutFile.txt"));
    for (int i = 0; i < SIZE; i++) {
        out.println("Value at: " + i + " = " + list.get(i));
    }
    out.close();
}

Eksempel på bruk av throws

public void writeList() throws IOException, IndexOutOfBoundsException {
public void writeList() throws IOException {

Spesifiserer hvilke unntak som kastes

Trenger ikke spesifisere RuntimeExceptions

Eksempel 1

public E next() {
    checkForComodification();
    if (nextIndex == size)
        throw new NoSuchElementException();

    lastReturned = next;
    next = next.next;
    nextIndex++;
    return lastReturned.element;

Eksempel 2

public Scanner(File source) throws FileNotFoundException {
  this((ReadableByteChannel)(new FileInputStream(source).getChannel()));
}

I Scanner sin konstruktør lages et nytt objekt av FileInputStream. Konstruktøren i dette objektet kaster et unntak. Scanner sin konstruktør kaster dette unntaket videre og vi må derfor behandle det når vi lager et nytt objekt av Scanner.

Tre typer unntak:

RuntimeException

Checked Exception

Error

Unchecked Exception

try {
    Scanner scan = new Scanner(new File("filnavn"));
    String navn = scan.next();
    String yrke = scan.next();

} catch (FileNotFoundException e) {
    System.out.println("Filen filnavn ble ikke funnet!");
    System.exit(-1);

} catch (NoSuchElementException e) {
    System.err.println("Filen er ikke komplett!");
    e.printStackTrace();
    System.exit(-1);
}

Eksempel

Kontrovers rundt unchecked exceptions

Hovedregel:

Hvis en klient kan innenfor rimelighetens grenser forventes å komme seg videre fra et unntak kaster vi en checked exception.

Hvis en klient ikke kan gjøre noe for å komme seg videre fra unntaket kaster vi en unchecked exception.

Lage sitt eget unntak

Nyttig for å differensiere mellom unntak som kommer fra din kode og unntak som kommer fra annen kode

Nyttig å lage et unntakshierarki (arv) for å kunne fange (catch) flere unntak i samme blokk.

public class IkkeFlereElementerException extends Exception {

    public IkkeFlereElementerException() {

    }    

    public IkkeFlereElementerException(String melding) {
        super(melding);
    }
}

Eksempel

Oppsummering

Når noe galt skjer kan et program kaste et unntak.

For å kaste et unntak bruker man throw og gir et unntaksobjekt som arver fra Throwable.

Man kan fange (catch) og behandle et unntak ved å bruke en kombinasjon av try, catch og finally.

Vi har unchecked exception (Error og RuntimeException) og checked exception (Alle andre subklasser av Exception) 

Eksempel på unntak i metoder

Et eksempel på en kallstakk

Vi får et unntak og må lete i kalltakken etter en unntaksbehandler

Kilder og henvisninger

  • https://docs.oracle.com/javase/tutorial/essential/exceptions/index.html
  • https://docs.oracle.com/javase/8/docs/api/java/lang/Throwable.html
  • https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html
  • https://docs.oracle.com/javase/8/docs/api/java/lang/RuntimeException.html

Alt om unntak finner dere her:

Det står også mye nyttig i dokumentasjonen:

Unntak

By borgli

Unntak

  • 1,689