Java - try-with-resourcess


Naredba try-with-resources automatski zatvara sve resurse na kraju izraza. Resurs je objekt koji se zatvara na kraju programa. Njegova sintaksa je:

try (resource declaration) {
  // Korištenje resursa
} catch (ExceptionType e1) {
  // Blok catch
}

Kao što se vidi iz gornje sintakse, izjavu try-with-resources proglašavamo prema:

  • Deklariranje i instanciranje resursa unutar klauzule try.
  • Specifikovanje i rukovanje svim izuzecima koji bi se mogli pojaviti tokom zatvaranja resursa.

Primjer 1: try-with-resources

import java.io.*;

class Main {
  public static void main(String[] args) {
    String line;
    try(BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
      while ((line = br.readLine()) != null) {
        System.out.println("Linija =>"+line);
      }
    } catch (IOException e) {
      System.out.println("IOException u try bloku=>" + e.getMessage());
    }
  }
}

U ovome primjeru koristimo instancu BufferedReader za čitanje podataka iz datoteke test.txt. Deklarisanje i instanciranje BufferedReader-a unutar naredbe try-with-resources osigurava da je njegova instanca zatvorena bez obzira na to izvršava li se naredba try normalno ili baca izuzetak. Ako se dogodi izuzetak, njime se može rukovati pomoću blokova za obradu izuzetaka ili ključne riječi throws.



Potisnuti izuzeci

U prethodnom primjeru izuzetak se može izbaciti iz izraza try-with-resources kada:

  • Datoteka test.txt nije pronađena.
  • Zatvaranje objekta BufferedReader.

Izuzetak se takođe može izbaciti iz try bloka, jer pročitana datoteka može uspjeti iz mnogo razloga u bilo kom trenutku. Ako se izuzetak izbaci iz bloka try i naredbe try-with-resources, izbacuje se izuzetak iz bloka try, a izuzetak iz izraza try-with-resources se potiskuje.



Dohvatanje potisnutih izuzetaka

U Javi 7 i novijim verzijama, potisnuti izuzeci se mogu dohvatiti pozivanjem metode Throwable.getSuppressed() iz izuzetka koji je izbacio blok try. Ova metoda vraća niz svih potisnutih izuzetaka. Potisnute izuzetke dobijamo u bloku catch.

catch(IOException e) {
  System.out.println("Bacanje izuzetka=>" + e.getMessage());
  Throwable[] suppressedExceptions = e.getSuppressed();
  for (int i=0; i<suppressedExceptions.length; i++) {
    System.out.println("Potisnuti izuzetak=>" + suppressedExceptions[i]);
  }
}


Prednosti korištenja try-with-resources

finally block nije potreban za zatvaranje resource

Prije nego što je Java 7 uvela ovu odliku, morali smo upotrijebiti finally blok kako bismo bili sigurni da je resurs zatvoren, kako bismo izbjegli curenje resursa. Evo programa koji je sličan primjeru 1. Međutim, u ovome smo programu smo upotrijebili finally blok za zatvaranje resursa.


Primjer 2: Zatvorite resurs pomoću finally bloka

import java.io.*;

class Main {
  public static void main(String[] args) {
    BufferedReader br = null;
    String line;

    try {
      System.out.println("Entering try block");
      br = new BufferedReader(new FileReader("test.txt"));
      while ((line = br.readLine()) != null) {
        System.out.println("Linija=>"+line);
      }
    } catch (IOException e) {
      System.out.println("IOException u try bloku=>" + e.getMessage());
    } finally {
      System.out.println("Ulaz finally bloka");
      try {
        if (br != null) {
          br.close();
        }
      } catch (IOException e) {
        System.out.println("IOException u finally bloku =>"+e.getMessage());
      }
    }
  }
}

Kao što možemo vidjeti iz gornjeg primjera, finally bloka za čišćenje resursa čini kod složenijim. Primijetite blok try...catch i u bloku finally? To je zato što se IOException može pojaviti i pri zatvaranju instance BufferedReader unutar ovog bloka, tako da se takođe hvata i rukuje njime. Naredba try-with-resources omogućava automatsko upravljanje resursima. Ne moramo izričito zatvarati resurse, jer ih JVM automatski zatvara. To čini kod čitljivijim i lakšim za pisanje.


2. try-with-resources s više resursa

U izjavi try-with-resources možemo deklarisati više resursa odvajajući ih tačka-zarezom ;.


Primjer 3: try s više resursa

import java.io.*;
import java.util.*;

class Main {
  public static void main(String[] args) throws IOException{
    try (Scanner scanner = new Scanner(new File("testRead.txt")); 
      PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) {
      while (scanner.hasNext()) {
        writer.print(scanner.nextLine());
      }
    }
  }
}

Ako se ovaj program izvršava bez generisanja izuzetka, objekt Scanner čita red iz datoteke testRead.txt i zapisuje ga u novu datoteku testWrite.txt. Kad se napravi više deklaracija, naredba try-with-resources zatvara te resurse obrnutim redosljedom. U ovome primjeru prvo se zatvara objekt PrintWriter, a zatim se zatvara objekt Scanner.