Neste tutorial, aprenderemos sobre a instrução try-with-resources para fechar recursos automaticamente.
A try-with-resources
instrução fecha automaticamente todos os recursos no final da instrução. Um recurso é um objeto a ser encerrado no final do programa.
Sua sintaxe é:
try (resource declaration) ( // use of the resource ) catch (ExceptionType e1) ( // catch block )
Como visto na sintaxe acima, declaramos a try-with-resources
instrução por,
- declarar e instanciar o recurso dentro da
try
cláusula. - especificando e tratando todas as exceções que podem ser lançadas ao fechar o recurso.
Nota: A instrução try-with-resources fecha todos os recursos que implementam a interface AutoCloseable.
Tomemos um exemplo que implemente a try-with-resources
declaração.
Exemplo 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("Line =>"+line); ) ) catch (IOException e) ( System.out.println("IOException in try block =>" + e.getMessage()); ) ) )
Saída se o arquivo test.txt não for encontrado.
IOException em try-with-resources block => test.txt (nenhum arquivo ou diretório)
Saída se o arquivo test.txt for encontrado.
Entrando no bloco try-with-resources Line => test line
Neste exemplo, usamos uma instância de BufferedReader para ler os dados do test.txt
arquivo.
Declarar e instanciar o BufferedReader dentro da try-with-resources
instrução garante que sua instância seja fechada, independentemente de a try
instrução ser concluída normalmente ou gerar uma exceção.
Se ocorrer uma exceção, ela pode ser tratada usando os blocos de tratamento de exceção ou a palavra-chave throws.
Exceções suprimidas
No exemplo acima, exceções podem ser lançadas da try-with-resources
instrução quando:
- O arquivo
test.txt
não foi encontrado. - Fechando o
BufferedReader
objeto.
Uma exceção também pode ser lançada do try
bloco, pois a leitura de um arquivo pode falhar por vários motivos a qualquer momento.
Se exceções forem lançadas do try
bloco e da try-with-resources
instrução, a exceção do try
bloco será lançada e a exceção da try-with-resources
instrução será suprimida.
Recuperando exceções suprimidas
No Java 7 e posterior, as exceções suprimidas podem ser recuperadas chamando o Throwable.getSuppressed()
método da exceção lançada pelo try
bloco.
Este método retorna uma matriz de todas as exceções suprimidas. Obtemos as exceções suprimidas no catch
bloco.
catch(IOException e) ( System.out.println("Thrown exception=>" + e.getMessage()); Throwable() suppressedExceptions = e.getSuppressed(); for (int i=0; i" + suppressedExceptions(i)); ) )
Vantagens de usar try-with-resources
Aqui estão as vantagens de usar try-with-resources:
1. por fim, não é necessário bloquear para fechar o recurso
Antes do Java 7 introduzir esse recurso, tínhamos que usar o finally
bloco para garantir que o recurso fosse fechado para evitar vazamentos de recursos.
Este é um programa semelhante ao Exemplo 1 . No entanto, neste programa, usamos o bloco final para fechar os recursos.
Exemplo 2: Fechar o recurso usando finally block
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("Line =>"+line); ) ) catch (IOException e) ( System.out.println("IOException in try block =>" + e.getMessage()); ) finally ( System.out.println("Entering finally block"); try ( if (br != null) ( br.close(); ) ) catch (IOException e) ( System.out.println("IOException in finally block =>"+e.getMessage()); ) ) ) )
Resultado
Inserindo o bloco try Line => linha do arquivo test.txt Entrando no bloco
Como podemos ver no exemplo acima, o uso de finally
bloco para limpar recursos torna o código mais complexo.
Observe o try… catch
bloco no finally
bloco também? Isso ocorre porque um IOException
também pode ocorrer ao fechar a BufferedReader
instância dentro desse finally
bloco, portanto, ele também é capturado e tratado.
A try-with-resources
instrução faz o gerenciamento automático de recursos . Não precisamos fechar explicitamente os recursos, pois a JVM os fecha automaticamente. Isso torna o código mais legível e fácil de escrever.
2. tentar com recursos com vários recursos
Podemos declarar mais de um recurso na try-with-resources
instrução, separando-os com um ponto e vírgula;
Exemplo 3: experimente com vários recursos
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()); ) ) ) )
Se este programa for executado sem gerar nenhuma exceção, o Scanner
objeto lê uma linha do testRead.txt
arquivo e a grava em um novo testWrite.txt
arquivo.
Quando várias declarações são feitas, a try-with-resources
instrução fecha esses recursos na ordem inversa. Neste exemplo, o PrintWriter
objeto é fechado primeiro e, em seguida, o Scanner
objeto é fechado.
Aprimoramento do Java 9 try-with-resources
No Java 7, há uma restrição à try-with-resources
instrução. O recurso precisa ser declarado localmente em seu bloco.
try (Scanner scanner = new Scanner(new File("testRead.txt"))) ( // code )
Se declarássemos o recurso fora do bloco em Java 7, ele teria gerado uma mensagem de erro.
Scanner scanner = new Scanner(new File("testRead.txt")); try (scanner) ( // code )
Para lidar com esse erro, o Java 9 aprimorou a try-with-resources
instrução para que a referência do recurso possa ser usada mesmo se não for declarada localmente. O código acima agora será executado sem nenhum erro de compilação.