Como usar Try With Resource em Java

Feb 21 2023
Como lidar com exceções usando a instrução try-with-resource A construção Java try with resources, também conhecida como Java try-with-resources, é um mecanismo de tratamento de exceções que pode fechar automaticamente recursos como um Java InputStream ou uma conexão JDBC quando você terminar de usá-los . A Oracle adicionou a construção try com recursos à linguagem Java em 2011 para ajudar a garantir que objetos como soquetes de rede, conexões de banco de dados e referências a arquivos e pastas sejam finalizados de forma limpa após seu uso.

Como lidar com exceções usando a instrução try-with-resource

A construção Java try with resources , também conhecida como Java try-with-resources , é um mecanismo de manipulação de exceção que pode fechar automaticamente recursos como um Java InputStream ou uma conexão JDBC quando você terminar de usá-los.

A Oracle adicionou a construção try com recursos à linguagem Java em 2011 para ajudar a garantir que objetos como soquetes de rede, conexões de banco de dados e referências a arquivos e pastas sejam finalizados de forma limpa após seu uso. A falha em fechar esses recursos depois que um desenvolvedor abre um identificador para eles pode causar vazamentos de memória , acionar rotinas de coleta de lixo evitáveis ​​e sobrecarregar a CPU de um servidor .

· Antes do Java 7
· Como usar a instrução try-with-resource?
· Por que devo usar a instrução try-with-resource?
· Exemplo
· Exceções suprimidas
· Vantagens de usar try-with-resources
· try-with-resources com vários recursos
· Java 9 — Variáveis ​​finais eficazes

Antes do Java 7

Em Java, se você usar um recurso como fluxos de entrada ou saída, sempre terá que fechá-lo após o uso. Ele também pode lançar exceções, portanto, deve estar em um bloco try-catch . O fechamento deve estar no bloco final . Este é pelo menos o caminho até o Java 7. Isso tem várias desvantagens:

  • Você teria que verificar se o seu recurso é nulo antes de fechá-lo
  • O fechamento em si pode lançar exceções, então você finalmente teve que conter outro try-catch
  • Programadores tendem a esquecer de fechar seus recursos

Como usar a instrução try-with-resource?

Ele foi inicialmente introduzido no Java 7 e toda a ideia por trás dele era que o desenvolvedor não precisa se preocupar com o gerenciamento de recursos que eles usam apenas em um bloco try -catch-finally . Isso é obtido removendo a necessidade de blocos finalizados , que os desenvolvedores usaram apenas para fechar recursos na prática.

Em Java, a instrução try-with-resources é uma instrução try que declara um ou mais recursos. O recurso é como um objeto que deve ser fechado após o término do programa. Quando a execução deixa o bloco try-with-resources , qualquer recurso aberto dentro do bloco try-with-resources é fechado automaticamente, independentemente de qualquer exceção ser lançada de dentro do bloco try-with-resources ou ao tentar fechar os recursos.

Para usar o recurso de linguagem try-with-resources do Java, as seguintes regras se aplicam:

  • Todos os objetos gerenciados por uma instrução try with resources devem implementar a interface AutoCloseable.
  • Múltiplos objetos AutoCloseable podem ser criados dentro do bloco try with resources do Java.
  • Os objetos declarados em uma instrução try with resources têm escopo dentro do bloco try, mas não nos blocos catch e finalmente.
  • O método close() de objetos declarados em um bloco try with resources é invocado independentemente de uma exceção ser lançada durante a execução.
  • Se uma exceção for lançada no método close(), ela pode ser categorizada como uma exceção suprimida .

O recurso referenciado pelo objeto AutoCloseable sempre será fechado se uma instrução try with resources for usada e possíveis vazamentos de memória geralmente causados ​​por uma má alocação de recursos forem eliminados.

Sintaxe

try(declare resources here) {
    // use resources
}
catch(FileNotFoundException e) {
    // exception handling
}

Simplificando, para ser fechado automaticamente, um recurso deve ser declarado e inicializado dentro do try :

try (PrintWriter writer = new PrintWriter(new File("test.txt"))) {
    writer.println("Hello World");
}

A maneira simples e óbvia de usar a nova funcionalidade try-with-resources é substituir o tradicional e detalhado bloco try-catch-finally .

Vamos comparar os exemplos de código a seguir.

O primeiro é um típico bloco try-catch-finally :

Scanner scanner = null;
try {
    scanner = new Scanner(new File("test.txt"));
    while (scanner.hasNext()) {
        System.out.println(scanner.nextLine());
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    if (scanner != null) {
        scanner.close();
    }
}"); background-repeat: no-repeat; background-position: center center; background-color: rgb(99, 177, 117);">Copy

try (Scanner scanner = new Scanner(new File("test.txt"))) {
    while (scanner.hasNext()) {
        System.out.println(scanner.nextLine());
    }
} catch (FileNotFoundException fnfe) {
    fnfe.printStackTrace();
}

Quando se trata de exceções, há uma diferença no bloco try-catch-finally e no bloco try-with-resources. Se uma exceção for lançada no bloco try e no bloco final, o método retornará a exceção lançada no bloco final.

Para try-with-resources, se uma exceção for lançada em um bloco try e em uma instrução try-with-resources, o método retornará a exceção lançada no bloco try. As exceções lançadas por try-with-resources são suprimidas, ou seja, podemos dizer que o bloco try-with-resources lança exceções suprimidas.

Por que eu tenho que usar a instrução try-with-resource?

A instrução try-with-resources garante que cada recurso seja fechado no final da execução da instrução . Se não fecharmos os recursos, isso pode constituir um vazamento de recursos e também o programa pode esgotar os recursos disponíveis para ele. isso é o que acontece principalmente quando você usa o bloco try-catch-finally

Antes do Java SE 7, você pode usar um bloco finalmente para garantir que um recurso seja fechado independentemente de a instrução try ser concluída normalmente ou abruptamente. O exemplo a seguir usa um bloco finalmente em vez de uma instrução try -with-resources:

static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
   
    FileReader fr = new FileReader(path);
    BufferedReader br = new BufferedReader(fr);
    try {
        return br.readLine();
    } finally {
        br.close();
        fr.close();
    }
}

Neste exemplo, se o método readLine lançar uma exceção e a instrução br.close() no bloco finalmente lançar uma exceção, o FileReader vazou. Portanto, use uma instrução try -with-resources em vez de um bloco final para fechar os recursos do seu programa.

Exemplo

O exemplo a seguir lê a primeira linha de um arquivo. Ele usa uma instância de FileReader e BufferedReader para ler os dados do arquivo. FileReader e BufferedReader são recursos que devem ser fechados após o término do programa:

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());
    }
  }
}

Exceções suprimidas

Se um bloco try lançar uma exceção e uma ou mais exceções forem lançadas pelo try-with-resources, as exceções lançadas pelo try-with-resources serão suprimidas. Em outras palavras, podemos dizer que as exceções lançadas por try-with-resources são exceções suprimidas.

Você pode obter essas exceções usando o método getSuppress() da classe Throwable.

Exemplo :

No exemplo acima, as exceções podem ser lançadas da instrução try-with-resources quando:

  • O arquivo test.txt não foi encontrado.
  • Fechando o objeto BufferedReader .

Se forem lançadas exceções do bloco try e da instrução try -with-resources , a exceção do bloco try será lançada e a exceção da instrução try-with-resources será suprimida.

Recuperando Exceções Suprimidas

No Java 7 e posterior, as exceções suprimidas podem ser recuperadas chamando o método Throwable.getSuppressed() da exceção lançada pelo bloco try .

getSuppress() Ele retorna um array contendo todas as exceções que foram suprimidas pela instrução try-with-resources. Se nenhuma exceção for suprimida ou a supressão estiver desativada, uma matriz vazia será retornada.

Obtemos as exceções suprimidas no bloco catch .

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

Aqui estão as vantagens de usar try-with-resources:

  • Código mais legível e fácil de escrever.
  • Gerenciamento automático de recursos.
  • O número de linhas de código é reduzido.
  • Quando vários recursos são abertos em try-with-resources, ele os fecha na ordem inversa para evitar qualquer problema de dependência.

Antes do Java 7 introduzir esse recurso, tínhamos que usar o bloco final para garantir que o recurso fosse fechado para evitar vazamentos de recursos.

Aqui está um programa semelhante ao Exemplo 1 . No entanto, neste programa, usamos o bloco final para fechar os recursos.

Exemplo: Fechar recurso usando o bloco finalmente

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());
      }
    }
  }
}

Entering try block
Line =>line from test.txt file
Entering finally block

Observe o bloco try…catch no bloco final também? Isso ocorre porque uma IOException também pode ocorrer ao fechar a instância BufferedReader dentro desse bloco final , de modo que ela também seja capturada e tratada.

A instrução try-with-resources 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.

try-with-resources Com vários recursos

Podemos declarar vários recursos perfeitamente em um bloco try-with-resources, separando-os com um ponto-e-vírgula:

try (Scanner scanner = new Scanner(new File("testRead.txt"));
    PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) {
    while (scanner.hasNext()) {
	writer.print(scanner.nextLine());
    }
}

Antes do Java 9, só podíamos usar novas variáveis ​​dentro de um bloco try-with-resources :

try (Scanner scanner = new Scanner(new File("testRead.txt")); 
    PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) { 
    // omitted
}"); background-repeat: no-repeat; background-position: center center; background-color: rgb(99, 177, 117);">Copy

final Scanner scanner = new Scanner(new File("testRead.txt"));
PrintWriter writer = new PrintWriter(new File("testWrite.txt"))
try (scanner;writer) { 
    // omitted
}"); background-repeat: no-repeat; background-position: center center; background-color: rgb(99, 177, 117);">Copy

Como mostrado acima, a variável do scanner é declarada final explicitamente, então podemos usá-la com o bloco try-with-resources . Embora a variável do gravador não seja explicitamente final, ela não muda após a primeira atribuição. Então, podemos usar a variável Writer também.

Bom aprendizado

Junte-se ao Grupo Mouad Oumous Java WhatsApp PARTICIPE

Junte-se ao canal de telegrama Mouad Oumous PARTICIPE

Apoie nossa publicação seguindo-a

Guia para Mapeamento de Objetos com ModelMapper em Java Introdução ao Spring Boot: Um Tutorial Abrangente para Iniciantes Spring Boot Security | SSO | OAuth2 com Okta Pergunta de entrevista baseada em fluxo Java8 mais comum — Parte 2 Codificação: nivelar uma matriz em Javascript Pergunta de entrevista baseada em fluxo Java8 mais comum — Parte 1