Java - throw i throws


U Javi se izuzetci mogu kategorizirati u dvije vrste:

  • Neprovjereni izuzeci (Unchecked Exceptions) - ne provjeravaju se za vrijeme kompajliranja, već za vrijeme izvođenja. Na primjer: ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException, izuzeci u klasi Error itd.
  • Provjereni izuzeci (Checked Exceptions) - provjeravaju se za vrijeme kompajliranja. Na primjer: IOException, InterruptException itd.

Obično ne moramo obrađivati nekontrolisane izuzetke. To je zato što do neprovjerenih izuzetaka dolazi zbog programskih pogrešaka. Dobra je praksa ispraviti ih umjesto rukovati njima. Sada ćemo se usredotočiti na to kako postupati s provjerenim izuzetaka pomoću throw i throws.



Java throws ključna riječ

Mi koristimo ključnu riječ throws u deklaraciji metode za deklarisanje vrste izuzetka koji se mogu pojaviti unutar nje. Sintaksa je:

accessModifier returnType methodName() throws ExceptionType1, ExceptionType2 … {
  // Kod
}

Kao što možete vidjeti iz gornje sintakse, možemo koristiti throws za deklarisanje više izuzetaka.


Primjer 1: Java throws ključna riječ

import java.io.*;

class Main {
  public static void findFile() throws IOException {
    // Kod koji može proizvesti IOException
    File newFile=new File("test.txt");
    FileInputStream stream=new FileInputStream(newFile);
  }

  public static void main(String[] args) {
    try{
      findFile();
    } catch(IOException e){
      System.out.println(e);
    }
  }
}

Prikaz koda iz gornjeg primjera izgledaće ovako:

java.io.FileNotFoundException: test.txt (No such file or directory)

Kad pokrenemo ovaj program, ako datoteka test.txt ne postoji, FileInputStream baca datoteku FileNotFoundException koja proširuje klasu IOException. Ako metoda ne obrađuje izuzetak, vrsta izuzetka koji se može pojaviti unutar nje mora biti naveden u klauzuli throws tako da ih metode dalje mogu obraditi ili specifikovati pomoću same ključne riječi throws. Metoda findFile() navodi da se IOException može izbaciti. Metoda main() poziva ovu metodu i obrađuje izuzetak ako je bačen.



Bacanje više iznimaka (Throwing multiple exceptions)

Evo kako možemo baciti više izuzetaka pomoću ključne riječi throws.

import java.io.*;

class Main {
  public static void findFile() throws NullPointerException, IOException, InvalidClassException {
    
    // Kod koji može proizvesti NullPointerException
    … … … 

    // Kod koji može proizvesti IOException
    … … … 

    // Kod koji može proizvesti InvalidClassException
    … … … 
  }

  public static void main(String[] args) {
    try{
      findFile();
    } catch(IOException e1){
      System.out.println(e1.getMessage());
    } catch(InvalidClassException e2){
      System.out.println(e2.getMessage());
    }
  }
}

Ovdje metoda findFile() navodi da u klauzuli throws može izbaciti NullPointerException, IOException i InvalidClassException. Imajte na umu da nismo obradili NullPointerException. To je zato što je to izuzetak koji se ne provjerava. Nije potrebno navesti ga u klauzuli throws i rukovati njime.



Ključna riječ throws Vs. try...catch...finally

Možda postoji nekoliko metoda koje mogu uzrokovati izuzetak. Pisanje try...catch za svaku metodu biće dosadno, a kod postaje dugačak i manje čitljiv. Ključna riječ throws je takođe korisna kada ste označili izuzetak (izuzetak koji se mora obraditi) koji ne želite uhvatiti u trenutnoj metodi.



Java throw ključna riječ

Ključna riječ throw koristi se za izričito izbacivanje jednog izuzetka. Kad se izuzme izuzetak, tok izvođenja programa prenosi se iz bloka try u blok catch. Unutar metode koristimo ključnu riječ throw. Sintaksa je:

throw throwableObject;

Objekt koji se može baciti je primjer klase Throwable ili potklase klase Throwable.


Primjer 2: Java throw ključna riječ

class Main {
  public static void divideByZero() {
    throw new ArithmeticException("Pokušaj dijeljenja s 0");
  }

  public static void main(String[] args) {
    divideByZero();
  }
}

Prikaz koda iz gornjeg primjera izgledaće ovako:

Exception in thread "main" java.lang.ArithmeticException: Trying to divide by 0
    at Main.divideByZero(Main.java:3)
    at Main.main(Main.java:7)
exit status 1

U ovom primjeru izričito bacamo ArithmeticException.


Primjer 3: Bacanje provjerenih izuzetaka

import java.io.*;

class Main {
  public static void findFile() throws IOException {
    throw new IOException("Datoteka nije pronađena!");
  }

  public static void main(String[] args) {
    try {
      findFile();
      System.out.println("Ostatak koda u try bloku");
    } catch (IOException e) {
      System.out.println(e.getMessage());
    }
  }
}

Prikaz koda iz gornjeg primjera izgledaće ovako:

Datoteka nije pronađena!

Metoda findFile() baca IOException s porukom koju smo prosljedili njezinom konstruktoru. Imajte na umu da, budući da je to provjereni izuzetak, moramo ga navesti u klauzuli throws. Metode koje pozivaju ovu metodu findFile() moraju ili obraditi ovaj izuzetak ili ga navesti pomoću same ključne riječi throws. Ovaj izuzetak smo obradili u metodi main(). Tokom izvođenja programa prenosi se iz bloka try u blok catch kada se pojavi izuzetak. Dakle, ostatak koda u bloku try preskače se i izvode naredbe u bloku catch.