Exceções e arquivos em Java
try, catch e finally. Lance suas próprias exceções e projete classes de exceção que informem exatamente o que deu errado. Depois, leia e grave arquivos de texto controlando caminhos, codificações e terminadores de linha, feche cada arquivo com segurança usando try-with-resources e desenvolva um programa que lide com arquivos ausentes e dados inválidos.BásicoAula 9 de 11 do curso Curso de Programação orientada a objetos com Java
O que você vai aprender
- Reconheça uma exceção quando um programa falhar, interprete o rastreamento da pilha para descobrir onde e por que ela ocorreu e situe qualquer exceção na hierarquia de classes de Java como verificada ou não verificada.
- Interprete uma exceção e seu rastreamento da pilhaExplique o que acontece quando uma instrução lança uma exceção, nomeie as exceções de execução comuns e suas causas e use um rastreamento da pilha para localizar o problema.
- Classifique exceções como verificadas ou não verificadasSitue qualquer exceção na hierarquia abaixo de Throwable, determine se ela é verificada ou não verificada e aplique a regra de que exceções verificadas devem ser capturadas ou declaradas.
- Interprete uma exceção e seu rastreamento da pilha
- Capture as exceções que um programa pode esperar, recupere a execução de forma adequada, trate vários tipos na ordem correta e execute o código de limpeza independentemente do que acontecer.
- Capture uma exceção e recupere a execuçãoEscreva uma instrução try-catch, acompanhe o fluxo de controle por ela e recupere a execução após uma entrada inválida em vez de deixar o programa falhar.
- Trate vários tipos de exceção na ordem corretaUse várias cláusulas catch ou uma captura múltipla, ordene-as da mais específica para a mais geral e decida onde um bloco try deve começar e terminar.
- Execute código de limpeza com finallyAdicione um bloco finally, acompanhe quando ele é executado em cada caminho de uma instrução try e evite erros que façam finally ocultar problemas.
- Capture uma exceção e recupere a execução
- Sinalize problemas em seus próprios métodos com throw, declare exceções verificadas com throws e crie classes de exceção que informem aos chamadores exatamente o que deu errado.
- Lance exceções e declare-as com throwsValide argumentos e o estado de objetos lançando exceções padrão, declare exceções verificadas em cabeçalhos de métodos e decida onde uma exceção deve ser tratada.
- Crie classes de exceção personalizadas e preserve a causaEscreva suas próprias classes de exceção verificadas ou não verificadas, lance-as antes de alterar o estado de um objeto e encapsule uma exceção de baixo nível sem perdê-la.
- Lance exceções e declare-as com throws
- Indique ao programa o arquivo correto, compreenda como o texto é armazenado como bytes e linhas e garanta que todo arquivo aberto seja fechado com try-with-resources.
- Trabalhe com caminhos, codificações e terminadores de linhaConstrua caminhos para arquivos, preveja onde Java procura um caminho relativo e explique como codificações de caracteres, terminadores de linha e formatos numéricos afetam arquivos de texto.
- Feche recursos automaticamente com try-with-resourcesUse try-with-resources para abrir e fechar arquivos e outros recursos, preveja a ordem de fechamento e explique como ele impede a perda de exceções.
- Trabalhe com caminhos, codificações e terminadores de linha
- Leia arquivos de texto linha por linha e transforme suas linhas em dados, grave resultados em arquivos ou acrescente-os ao final e combine tudo em um programa que lide com arquivos ausentes e registros inválidos.
- Leia um arquivo de texto e transforme suas linhas em dadosLeia um arquivo com Scanner, Files.readAllLines ou BufferedReader, divida e converta cada linha e ignore ou informe linhas que não correspondam ao formato esperado.
- Grave arquivos de texto e acrescente conteúdo ao finalGrave texto em um arquivo novo ou existente, acrescente conteúdo sem apagar o que já está lá e garanta que tudo o que for gravado realmente chegue ao arquivo.
- Desenvolva um programa robusto de processamento de arquivosCombine leitura, análise e conversão, exceções e gravação em um programa que pare de forma controlada em falhas no processamento do arquivo inteiro, ignore e informe registros inválidos e evite saídas parciais.
- Leia um arquivo de texto e transforme suas linhas em dados
Guia de estudo de Exceções em Java
1Compreenda o que são exceções e como Java as classifica
Um programa pode compilar com sucesso e ainda falhar ao receber um vetor vazio, texto inválido ou um arquivo ausente. O objeto de exceção e seu rastreamento da pilha fornecem evidências sobre essa falha. Acompanhe o rastreamento pelas chamadas de método ativas e use a hierarquia de classes para decidir se Java exige uma decisão de tratamento em tempo de compilação. Isso prepara você para distinguir defeitos a corrigir de problemas esperados dos quais seu programa pode se recuperar.
1.1 Encontre a instrução que falhou
Uma exceção é um objeto que descreve um problema que interrompe um programa em execução. Lançá-la interrompe a instrução atual. Java ignora o restante do trabalho normal até encontrar um tratador compatível; sem ele, a exceção passa de volta pelos métodos que o chamaram.
Reconheça o tipo de problema
A falta de um ponto e vírgula é um erro de compilação: o programa não consegue compilar. Uma exceção ocorre quando o código compilado é executado com dados que provocam um problema.
| Exceção | Causa típica |
|---|---|
ArithmeticException | Divisão inteira por zero |
ArrayIndexOutOfBoundsException | a[3] quando o vetor tem comprimento 3 |
IndexOutOfBoundsException | list.get(list.size()) |
NullPointerException | Chamada de um método por meio de null |
NumberFormatException | Integer.parseInt("12a") |
InputMismatchException | Scanner.nextInt() encontra “dez” |
ClassCastException | Conversão de um objeto para uma classe à qual ele não pertence |
Os índices de vetores começam em 0, então comprimento 3 significa índices válidos 0, 1 e 2. A divisão em ponto flutuante segue regras diferentes: 10.0 / 0 produz Infinity; ela não lança a exceção de divisão inteira.
Leia um rastreamento de cima para baixo
Aqui está uma classe completa, sem linhas em branco antes da primeira linha:
public class Average {
static int average(int[] values) {
int sum = 0;
for (int value : values) sum += value;
return sum / values.length;
}
public static void main(String[] args) {
int[] values = new int[0];
System.out.println(average(values));
}
}
O vetor está vazio, portanto seu comprimento é 0. A divisão na linha 5 falha. O rastreamento é:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Average.average(Average.java:5)
at Average.main(Average.java:9)
- Leia a primeira linha para identificar a classe e a mensagem da exceção.
- Leia o primeiro registro de ativação com
atpara identificar o ponto em que o problema foi detectado. - Leia para baixo para encontrar os chamadores:
mainchamouaveragena linha 9. - Se os primeiros registros pertencerem à biblioteca de Java, encontre o primeiro que menciona sua própria classe. Para uma chamada de
Integer.parseIntque falhou, registros da biblioteca podem preceder a chamada em seu código.
O rastreamento segue a pilha de chamadas, a cadeia de chamadas de método ativas. Ele indica onde investigar, mas o valor inválido pode ter sido criado antes. Aqui a divisão detecta o problema; o chamador forneceu o vetor vazio. Decida se uma entrada vazia deve ser rejeitada ou tratada antes de calcular uma média.
Examine o objeto de exceção
e.getMessage() retorna a mensagem e pode retornar null. e.toString() inclui o nome da classe e, quando presente, a mensagem. e.printStackTrace() exibe o rastreamento no erro padrão. Uma seção Caused by: mostra uma exceção anterior preservada dentro de um encapsulador.
Mensagens de NullPointerException geradas pela JVM normalmente identificam a expressão nula. Uma exceção criada explicitamente pode ter uma mensagem personalizada ou nenhuma. Acompanhe a referência até o ponto em que ela deveria ter recebido um objeto.
Uma exceção sem tratamento que sai de main encerra a thread principal; isso encerra um programa com uma única thread. Corrija defeitos como índices incorretos no código. Planeje a recuperação para problemas externos esperados, como um arquivo ausente ou uma entrada inválida do usuário.
Principais conclusões
- Uma exceção interrompe a execução normal; instruções ignoradas não são retomadas automaticamente.
- Leia a classe e a mensagem da exceção e acompanhe os registros de ativação desde a falha detectada até seus chamadores.
- Registros de ativação da biblioteca podem aparecer antes do primeiro registro em seu próprio código.
- A instrução que falhou pode revelar um valor inválido criado anteriormente.
- Corrija defeitos de programação e trate falhas esperadas de entrada ou de arquivos.
1.2 Exceções verificadas e não verificadas
As classes de exceção usam as regras de herança que você já conhece. Um objeto lançado de uma subclasse também pertence à sua superclasse, o que explica tanto as categorias de exceção de Java quanto a forma como um tratador corresponde a elas.
Acompanhe a hierarquia
Somente objetos de Throwable ou de suas subclasses podem ser lançados. Dois ramos principais estão abaixo dela:
Throwable
Error
OutOfMemoryError
StackOverflowError
Exception
RuntimeException
IllegalArgumentException
NumberFormatException
NullPointerException
IndexOutOfBoundsException
ArrayIndexOutOfBoundsException
IOException
FileNotFoundException
NoSuchFileException
Error descreve falhas graves do ambiente de execução. Uma aplicação comum não deve tentar se recuperar de um heap esgotado ou de uma pilha esgotada por recursão infinita. Exception descreve problemas que uma aplicação pode tratar, incluindo seu ramo RuntimeException.
| Categoria | Classes | Exigência do compilador |
|---|---|---|
| Não verificada | RuntimeException, Error e suas subclasses | Capturar ou declarar é opcional |
| Verificada | Todas as outras subclasses de Throwable | Capturar ou declarar quando o código puder lançá-las |
Ambos os tipos são lançados em tempo de execução. A palavra “verificada” descreve a verificação do tratamento pelo compilador, não um momento anterior em que a falha ocorre. Não verificada também não significa inofensiva: uma referência nula sem tratamento pode interromper um programa.
Aplique a regra de capturar ou declarar
A leitura de um arquivo pode falhar mesmo em código correto. Um método auxiliar pode deixar a decisão para seu chamador:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
class Names {
static List<String> load(Path file) throws IOException {
return Files.readAllLines(file);
}
}
Files.readAllLines pode lançar a exceção verificada IOException. A declaração passa essa possibilidade ao chamador, que também deve capturá-la ou declará-la. Remover throws IOException sem adicionar um tratador faz o método auxiliar falhar na compilação. Um método que usa Integer.parseInt não tem uma obrigação equivalente imposta pelo compilador porque NumberFormatException é não verificada.
Falhas verificadas frequentemente descrevem condições para as quais um chamador pode se preparar, como o desaparecimento de um arquivo. Falhas de execução frequentemente identificam defeitos ou argumentos inválidos. Essas são razões úteis de projeto, mas a cadeia de superclasses determina a categoria. Uma classe personalizada que estende RuntimeException permanece não verificada mesmo quando um chamador poderia se recuperar.
Identifique tratadores compatíveis por meio da herança
catch (IOException e) pode tratar uma FileNotFoundException ou NoSuchFileException. catch (Exception e) também captura exceções de execução; ele pode transformar um defeito de código em uma mensagem enganosa sobre a entrada. catch (Throwable e) também alcança o ramo Error e raramente é apropriado para uma recuperação comum.
Para classificar uma classe desconhecida, acompanhe sua herança para cima na documentação da API. InputMismatchException estende NoSuchElementException, que estende RuntimeException, portanto é não verificada. InterruptedException estende Exception fora do ramo de execução, portanto é verificada. Declarar um tipo não verificado em uma cláusula throws é permitido, mas não altera sua categoria.
Principais conclusões
RuntimeException,Errore todas as suas subclasses são não verificados.- Outras subclasses de
Throwablesão verificadas; o código que pode lançá-las deve capturá-las ou declará-las. - Exceções verificadas e não verificadas ocorrem em tempo de execução.
- Uma captura para uma superclasse também corresponde às suas subclasses.
- Um tratador abrangente de
Exceptionpode ocultar defeitos de programação. - Classifique uma exceção desconhecida por sua cadeia de superclasses.
2Trate exceções com try, catch e finally
Tratar uma falha altera quais instruções são executadas em seguida. Um tratador útil deve corresponder à exceção e deixar o programa pronto para continuar, enquanto a limpeza também deve ser executada nos caminhos que saem antecipadamente. Acompanhe conversões e laços passo a passo, escolha tratadores específicos antes dos gerais e coloque o bloco protegido em torno do trabalho que deve falhar em conjunto. Depois, acompanhe como finally se comporta quando uma exceção se propaga ou um método retorna.
2.1 Recupere a execução após uma conversão malsucedida
Um bloco try delimita um trabalho que pode falhar. Um bloco catch compatível dá ao programa uma próxima ação útil, como pedir outro valor. Tratar a exceção não repete a instrução que falhou automaticamente.
Acompanhe os ramos
System.out.println("A");
try {
System.out.println("B");
int value = Integer.parseInt("4x");
System.out.println("C");
} catch (NumberFormatException e) {
System.out.println("D: " + e.getMessage());
}
System.out.println("E");
A saída é A, B, D: For input string: "4x" e E, cada um em sua própria linha. A conversão falha, então Java ignora C e entra no tratador compatível. Quando esse tratador termina normalmente, a execução continua após toda a instrução. Se a conversão for bem-sucedida, o tratador é ignorado. Se o bloco lançar uma ArithmeticException, esse tratador não corresponderá a ela; a exceção se propagará.
Tente novamente com uma nova entrada
Leia uma linha inteira antes de convertê-la. O laço abaixo aceita um número inteiro e trata o fim da entrada do teclado informando que nenhum valor foi fornecido:
import java.util.Scanner;
class WholeNumbers {
static int readWholeNumber(Scanner in) {
while (in.hasNextLine()) {
String line = in.nextLine();
try {
return Integer.parseInt(line.trim());
} catch (NumberFormatException e) {
System.out.println("Please enter a whole number.");
}
}
throw new IllegalStateException("No number supplied");
}
}
Para as entradas “vinte” e “20”, o tratador exibe a mensagem uma vez, o laço lê uma nova linha e o método retorna 20. trim() remove os caracteres de espaço em branco ao redor: sem isso, Integer.parseInt(" 20") falha. A conversão aceita um sinal opcional e algarismos que representam um inteiro dentro do intervalo permitido.
Um scanner baseado em unidades de entrada precisa de outra correção. Quando nextInt() encontra “dez”, sua InputMismatchException deixa essa unidade sem ser lida. Capturar a exceção e chamar nextInt() novamente repete a falha para sempre. Consuma a unidade inválida com next() ou descarte a linha com nextLine() antes de tentar novamente. hasNextInt() pode verificar uma unidade antes da conversão.
Mantenha o estado recuperado utilizável
Uma variável declarada dentro de try existe apenas nesse bloco. Se o código posterior precisar do resultado, declare-a fora e faça com que cada caminho que continua atribua um valor válido:
int quantity;
try {
quantity = Integer.parseInt("bad");
} catch (NumberFormatException e) {
quantity = 0;
}
System.out.println(quantity);
Zero só é adequado aqui se o programa o definir como uma alternativa válida. Deixar quantity sem atribuição no tratador causa um erro de atribuição definitiva em tempo de compilação.
Capture o tipo específico que você consegue tratar. Um tratador vazio perde o problema silenciosamente; um catch (Exception e) abrangente pode classificar um defeito de referência nula como um número inválido. A recuperação deve pedir outra entrada, ignorar um item, escolher um valor padrão válido, informar a falha ou repassar uma exceção significativa. Para limites simples e previsíveis, verifique primeiro: index >= 0 && index < list.size() impede índices de lista negativos e grandes demais.
Principais conclusões
- Um tratador compatível é executado após o restante do bloco
tryque falhou ser ignorado. - Um laço deve ler uma nova entrada antes de tentar novamente.
Scanner.nextInt()deixa uma unidade de entrada incompatível sem ser lida.- Todo caminho que continua deve deixar as variáveis usadas depois inicializadas com valores adequados.
2.2 Escolha os tratadores e o trabalho que eles protegem
Um arquivo pode estar ausente, ilegível ou cheio de registros malformados. Essas falhas precisam de respostas diferentes. Vários tratadores permitem que um try as distinga, enquanto a posição do bloco determina quanto trabalho é interrompido quando algo falha.
Coloque os tratadores específicos primeiro
Java testa os tratadores de cima para baixo e executa o primeiro compatível. Ele não continua executando tratadores posteriores para a mesma exceção.
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
class FirstCount {
static void show(Path file) {
try {
int count = Integer.parseInt(Files.readString(file).trim());
System.out.println(count);
} catch (NoSuchFileException e) {
System.out.println("File not found: " + file.toAbsolutePath());
} catch (IOException e) {
System.out.println("Could not read: " + file.toAbsolutePath());
} catch (NumberFormatException e) {
System.out.println("The file must contain one whole number.");
}
}
}
NoSuchFileException estende IOException, portanto deve vir primeiro. Inverter a ordem torna o tratador específico inalcançável e impede a compilação. A exceção de conversão não tem relação de herança com IOException, então esses dois tratadores podem aparecer em qualquer ordem.
Um tratador de exceção verificada também deve ser relevante para o trabalho protegido. Capturar IOException em torno apenas de int count = 5; é rejeitado porque esse bloco não pode lançá-la. Essa restrição não se aplica da mesma forma aos tipos não verificados ou aos tipos abrangentes Exception e Throwable.
Compartilhe um tratador quando a resposta for a mesma
Uma captura múltipla une tipos de exceção sem relação de herança com |:
try {
String[] parts = "Ana".split(",");
int age = Integer.parseInt(parts[1]);
System.out.println(age);
} catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
System.out.println("Invalid record: " + e.getMessage());
}
Aqui o segundo campo ausente provoca a exceção de índice. Um campo presente, mas não numérico, provocaria a exceção de conversão, e ambos recebem a mesma resposta. O parâmetro da captura múltipla é implicitamente final. As alternativas não podem ser uma subclasse e sua superclasse: FileNotFoundException | IOException é inválido porque IOException já abrange ambas.
Decida o que uma falha deve fazer o programa ignorar
Considere os textos “3”, “x” e “5”. Com um try em torno de todo o laço, o processamento para em “x” e a soma até então é 3. Coloque o try dentro do laço para recuperar a execução separadamente para cada item:
int sum = 0;
for (String text : new String[] {"3", "x", "5"}) {
try {
sum += Integer.parseInt(text);
} catch (NumberFormatException e) {
System.out.println("Skipped: " + text);
}
}
System.out.println(sum);
Isso exibe Skipped: x e depois 8. O laço continua porque seu corpo tratou a falha daquele registro. Tratadores aninhados são procurados para fora a partir do bloco protegido mais interno; um tratador interno incompatível dá uma chance ao externo. Escolha a menor unidade de trabalho que deve falhar em conjunto: um registro para dados inválidos, a operação de arquivo para uma falha de leitura.
Principais conclusões
- Java executa no máximo um tratador compatível para cada exceção.
- Capture uma subclasse antes de sua superclasse.
- A captura múltipla compartilha uma resposta entre tipos de exceção sem relação de herança.
- A captura múltipla não pode combinar uma superclasse com sua subclasse.
- Coloque a recuperação de falhas em registros dentro do laço para continuar com os registros posteriores.
2.3 Execute a limpeza antes da transferência de controle
Algum trabalho deve ocorrer independentemente de uma operação ter sucesso ou falhar. Um bloco finally é executado quando o controle sai de sua instrução try, inclusive quando uma exceção se propaga ou um método retorna.
Acompanhe uma exceção sem tratador compatível
try {
System.out.println("1");
int[] values = new int[2];
values[2] = 7;
System.out.println("2");
} catch (NumberFormatException e) {
System.out.println("3");
} finally {
System.out.println("4");
}
System.out.println("5");
Apenas 1 e 4 são exibidos antes de a ArrayIndexOutOfBoundsException se propagar. O índice 2 está fora do vetor de dois elementos. O tratador não é compatível, mas finally ainda é executado. A instrução que exibe 5 está fora do bloco de limpeza, portanto a exceção que se propaga faz com que ela seja ignorada.
Se o trabalho protegido lançar uma NumberFormatException compatível após exibir 1, o tratador exibirá 3, a limpeza exibirá 4 e a execução continuará até 5. Em um caminho bem-sucedido, nenhum tratador é executado, mas a limpeza ainda ocorre.
Valores de retorno são preparados antes da limpeza
class Cleanup {
static int result() {
try {
return 1;
} finally {
System.out.println("cleanup");
}
}
}
A expressão de retorno é avaliada primeiro. Java então exibe cleanup, e o chamador recebe 1. Um break ou continue que sai de uma região protegida também executa sua limpeza antes que a transferência de controle ocorra.
Mantenha return fora de finally. Um return 2; ali substituiria o valor de retorno pendente e poderia até descartar uma exceção pendente. Uma exceção lançada pela limpeza também pode substituir a falha original. A limpeza não deve introduzir um segundo resultado concorrente. A opção -Xlint:finally do compilador emite um aviso quando um bloco finally não pode terminar normalmente.
Feche um objeto somente se ele tiver sido aberto
O padrão manual mais antigo precisa de uma variável visível ao bloco de limpeza:
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Scanner;
class ManualRead {
static void firstLine(Path file) throws IOException {
Scanner sc = null;
try {
sc = new Scanner(file, StandardCharsets.UTF_8);
if (sc.hasNextLine()) System.out.println(sc.nextLine());
if (sc.ioException() != null) throw sc.ioException();
} finally {
if (sc != null) sc.close();
}
}
}
Se a abertura falhar, sc ainda será null, portanto a verificação impede que a limpeza lance uma nova exceção de referência nula. Para objetos que podem ser fechados, try-with-resources elimina esse controle manual e lida com falhas concorrentes com mais segurança.
finally não é uma garantia contra a parada da máquina. System.exit encerra a JVM sem executar essa limpeza; uma falha ou perda de energia também a impede. Um laço infinito que nunca sai do bloco também nunca chega ao seu finally.
Principais conclusões
finallyé executado na conclusão normal, em exceções capturadas e não capturadas e em transferências de controle comoreturn.- Uma expressão de retorno é avaliada antes da execução da limpeza.
- O código após uma instrução
tryé ignorado quando uma exceção se propaga;finallyainda é alcançado. - Um retorno ou uma exceção lançada em
finallypode ocultar o resultado original. - Try-with-resources é a escolha usual para fechar recursos de arquivo.
- O encerramento da JVM ou um bloco que nunca termina pode impedir a limpeza.
3Lance exceções e projete suas próprias exceções
Uma solicitação inválida é mais fácil de diagnosticar antes que altere um objeto. Seus métodos podem rejeitar argumentos ou estados inválidos com exceções padrão e sinalizar problemas do domínio com classes personalizadas. A declaração do método informa aos chamadores sobre falhas verificadas; a herança limita o que uma sobrescrita pode acrescentar. Ao transformar uma falha de baixo nível em outra mais útil, preserve sua causa para que o chamador receba tanto o contexto quanto as evidências originais para o diagnóstico.
3.1 Sinalize argumentos e estados inválidos
Seus métodos podem rejeitar solicitações inválidas antes de alterar um objeto. Escolha uma exceção que identifique o problema e permita ao chamador responder.
Lance um objeto imediatamente
class Percentage {
private int value;
public void setPercentage(int value) {
if (value < 0 || value > 100) {
throw new IllegalArgumentException(
"percentage must be 0 to 100, was " + value);
}
this.value = value;
}
}
Chamar setPercentage(120) lança uma exceção com a mensagem percentage must be 0 to 100, was 120. A atribuição não foi executada, portanto o campo mantém seu valor anterior. Isso é falha imediata: informe a solicitação inválida no ponto em que você consegue explicá-la. A mesma verificação em um construtor impede que um objeto inválido seja retornado.
throw precisa de um objeto de exceção, como em throw new IllegalArgumentException("bad quantity");. Um nome de classe sozinho não é um objeto. Uma instrução comum diretamente após um throw incondicional no mesmo bloco é inalcançável.
| Problema | Exceção padrão |
|---|---|
| O argumento tem um valor inválido | IllegalArgumentException |
| O objeto está no estado inadequado para a chamada | IllegalStateException |
Uma referência a objeto obrigatória é null | NullPointerException |
| A operação não é oferecida pela classe | UnsupportedOperationException |
| A posição está fora de uma coleção | IndexOutOfBoundsException |
Objects.requireNonNull(name, "name must not be null"), de java.util.Objects, é uma forma prática de verificar se uma referência é nula. Um pedido já enviado que rejeita outro item representa um problema de estado; uma quantidade negativa de itens é um problema de argumento.
Declare o que pode sair do método
Um método auxiliar de leitura de arquivos pode declarar sua falha verificada:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
class NameLoader {
static List<String> loadNames(Path file) throws IOException {
return Files.readAllLines(file);
}
}
throw é uma instrução executável. throws pertence à declaração do método e informa aos chamadores quais falhas verificadas eles devem tratar. Ela não captura uma falha nem faz o método continuar depois dela. Cada chamador deve capturar IOException ou declará-la por sua vez. Uma captura também pode relançar o mesmo objeto com throw e;.
Capture a exceção onde uma resposta útil for possível. Um método auxiliar geralmente não pode pedir ao usuário que selecione outro arquivo, mas main pode. Exibir “erro” e retornar uma lista vazia confundiria um arquivo ausente com um arquivo realmente vazio. Em um pequeno experimento, main pode declarar throws IOException; um programa finalizado trata falhas esperadas com mensagens úteis. Tipos não verificados podem ser declarados para documentação, embora o compilador não exija isso.
Respeite o contrato herdado
Se uma interface declarar read() throws IOException, um método que o sobrescreve pode declarar IOException, uma subclasse verificada mais específica ou nenhuma exceção verificada. Ele não pode ampliar a declaração para Exception. Pode declarar tipos não verificados. Uma sobrescrita de Object.toString() não pode adicionar IOException, pois o método herdado não declara exceções verificadas. Chamadas por meio do tipo da interface ainda devem tratar a IOException declarada, mesmo quando uma implementação não declara nenhuma.
Principais conclusões
- Use
throwcom um objeto de exceção para interromper uma operação inválida. - Valide antes de alterar campos ou coleções.
throwsdeclara uma possível falha; não a trata.- Capture a exceção onde uma recuperação útil for possível; caso contrário, passe a falha ao chamador.
- Métodos que sobrescrevem outros não podem adicionar exceções verificadas novas ou mais abrangentes.
3.2 Descreva falhas do domínio e preserve suas causas
Uma exceção padrão muitas vezes é suficiente. Crie uma classe personalizada quando os chamadores precisarem reconhecer um problema específico do programa, como estoque insuficiente ou um registro de dados malformado, e responder a ele de forma diferente.
Escolha a superclasse de forma intencional
Estender Exception cria uma exceção verificada. Estender RuntimeException cria uma exceção não verificada. Use a opção verificada quando os chamadores devem se preparar para uma falha recuperável do domínio; use a opção não verificada para uso incorreto ou um defeito de programação.
class OutOfStockException extends Exception {
public OutOfStockException(String message) {
super(message);
}
}
super(message) armazena a mensagem no mecanismo de exceção herdado, então getMessage() a retorna. Por convenção, o nome da classe termina em Exception. Campos adicionais e métodos de acesso podem apresentar detalhes estruturados, como as quantidades solicitada e disponível.
Mantenha o estoque inalterado após uma falha
import java.util.HashMap;
class Inventory {
private final HashMap<String, Integer> stock = new HashMap<>();
Inventory() {
stock.put("pens", 12);
}
void remove(String item, int quantity) throws OutOfStockException {
if (quantity <= 0) {
throw new IllegalArgumentException("quantity must be positive");
}
int available = stock.getOrDefault(item, 0);
if (quantity > available) {
throw new OutOfStockException("Requested " + quantity
+ " of " + item + ", only " + available + " in stock");
}
stock.put(item, available - quantity);
}
}
Começando com 12 canetas, remover 5 deixa 7. Uma solicitação posterior de 10 lança uma exceção, e 7 permanecem porque a atualização vem depois de todas as verificações. O chamador deve tratar ou declarar a falha verificada de estoque; a falha de quantidade inválida é não verificada. Um programa que precise de uma resposta distinta para um item desconhecido poderia usar uma UnknownItemException relacionada, com ambos os tipos do domínio sob uma classe base InventoryException.
Encapsule sem perder o problema original
Um analisador pode transformar uma falha de conversão de baixo nível em uma falha em um registro:
class InvalidRecordException extends Exception {
public InvalidRecordException(String message) {
super(message);
}
public InvalidRecordException(String message, Throwable cause) {
super(message, cause);
}
}
Dentro do método de análise e conversão, um tratador pode fazer isto:
catch (NumberFormatException e) {
throw new InvalidRecordException(
"Line 3: quantity is not a number: x", e);
}
O encapsulador fornece ao chamador uma categoria significativa e o número da linha. Seu getCause() retorna a NumberFormatException original, e um rastreamento exibido preserva uma seção Caused by:. Construir uma nova exceção apenas com a mensagem antiga perde o objeto original e seu rastreamento.
java.io.UncheckedIOException é um encapsulador não verificado pronto, específico para IOException. Seus construtores aceitam a causa, com uma mensagem opcional. Ele pode transportar uma falha de arquivo por uma sobrescrita que não pode adicionar uma declaração de exceção verificada. O encapsulamento altera o tipo que o chamador vê; não corrige o problema do arquivo. Mantenha decisões comuns de laço como condições e break, sem criar exceções para o fluxo rotineiro.
Principais conclusões
- Classes personalizadas permitem que chamadores reconheçam falhas significativas do domínio.
- Estenda
Exceptionpara uma classe verificada ouRuntimeExceptionpara uma classe não verificada. - Chame
super(message)para preservar uma mensagem útil para o diagnóstico. - Valide toda a solicitação antes de atualizar o estado.
- Passe a exceção original como causa ao encapsulá-la.
UncheckedIOExceptiontransporta umaIOExceptioncomo uma falha não verificada.
4Localize arquivos e feche recursos com segurança
Um arquivo de texto deve ser encontrado, decodificado e fechado corretamente. Um caminho relativo depende do diretório de trabalho, enquanto bytes só se tornam caracteres legíveis por meio da codificação correta. Texto numérico e terminadores de linha trazem suas próprias escolhas de portabilidade. Depois que um arquivo é aberto, try-with-resources o libera em toda saída e mantém a falha principal visível caso o fechamento também falhe. Essas escolhas tornam o código posterior de leitura e gravação mais confiável.
4.1 Faça arquivos de texto funcionarem em diferentes computadores
Um arquivo armazena bytes, enquanto seu programa trabalha com caracteres e números. Uma leitura bem-sucedida precisa da localização correta, da codificação de caracteres correta e de uma convenção clara para linhas e texto numérico.
Encontre a localização real
Um caminho relativo parte do diretório de trabalho do programa. Ele não parte da pasta que contém o código-fonte. Um caminho absoluto parte da raiz do sistema de arquivos, como /home/ana/data/scores.txt, ou da raiz de uma unidade no Windows.
Path file = Path.of("data", "scores.txt");
System.out.println(System.getProperty("user.dir"));
System.out.println(file.toAbsolutePath());
System.out.println(file.getFileName());
Importe java.nio.file.Path. Criar esse Path não abre nada nem verifica se algo existe. toAbsolutePath() revela onde Java procurará, e getFileName() fornece scores.txt. Uma IDE frequentemente usa a pasta do projeto como diretório de trabalho. Barras normais em "data/scores.txt" funcionam no Windows, Linux e macOS. Um literal de caminho do Windows que usa barras invertidas precisa de escape, como em "C:\\data\\scores.txt". A classe mais antiga java.io.File também representa uma localização; converta com toPath() ou toFile().
Associe bytes a caracteres
UTF-8 codifica todos os caracteres Unicode. Caracteres latinos básicos ocupam um byte; os demais ocupam de dois a quatro. O texto “café” contém quatro caracteres, mas cinco bytes em UTF-8 porque “é” ocupa dois. Ler esses bytes como ISO-8859-1 pode produzir “café”. Use a codificação que foi usada na gravação.
Os métodos de texto de Files usam UTF-8 por padrão. Classes como FileWriter e um scanner aberto sem uma codificação usam a codificação de caracteres padrão, que passou a ser UTF-8 no Java 18; instalações mais antigas podem ser diferentes. StandardCharsets.UTF_8, de java.nio.charset, torna a escolha explícita. Bytes inválidos lidos por Files.readAllLines produzem MalformedInputException, uma subclasse de IOException.
Leia linhas sem deixar terminadores
| Convenção | Escape em cadeia de caracteres Java |
|---|---|
| Terminador de linha do Linux e macOS | \n |
| Terminador de linha típico do Windows | \r\n |
Com um terminador após cada linha, “a” e “b” precisam de quatro bytes com terminadores LF e seis com terminadores CRLF. BufferedReader.readLine(), Files.readAllLines e Scanner.nextLine() removem terminadores de linha reconhecidos. Dividir uma cadeia completa com split("\n") deixa o \r do Windows, então converter "12\r" com parseInt falha. Prefira métodos de leitura de linhas ou remova os espaços do texto. System.lineSeparator() e o formato %n produzem o terminador do sistema atual.
Mantenha a consistência em arquivos numéricos
Integer.parseInt aceita texto inteiro, sem separador decimal. Double.parseDouble("3.5") aceita um ponto; Double.parseDouble("3,5") falha. Esses métodos de análise e conversão ignoram a configuração regional. Os métodos numéricos de Scanner e a formatação decimal comum seguem a configuração regional, então configurações alemãs ou holandesas podem esperar “3,5” e produzir “3,50”. Use scanner.useLocale(Locale.ROOT) e String.format(Locale.ROOT, "%.2f", value) para dados com ponto decimal; importe java.util.Locale.
Localizações inexistentes normalmente produzem NoSuchFileException com Files ou Scanner(Path), enquanto construtores mais antigos que recebem nomes de arquivo podem produzir FileNotFoundException. Falhas de permissão podem produzir AccessDeniedException. Essas são falhas verificadas de entrada e saída: uma expressão de caminho correta, por si só, não pode impedi-las.
Principais conclusões
- Caminhos relativos são resolvidos a partir do diretório de trabalho.
- Criar um
Pathnão abre nem verifica o arquivo. - Use a mesma codificação na leitura e na gravação; escolha UTF-8 explicitamente onde os padrões podem variar.
- Métodos de leitura de linhas removem terminadores LF, CRLF e CR.
Double.parseDoubleusa ponto; métodos numéricos sensíveis à configuração regional precisam de uma configuração escolhida.- Abrir e ler arquivos ainda exige tratamento de exceções verificadas.
4.2 Deixe Java fechar cada recurso aberto
Um arquivo aberto usa um recurso do sistema operacional. Fechá-lo libera o recurso e descarrega a saída pendente de um gravador. Esquecer o fechamento pode esgotar os limites de arquivos abertos, perder texto armazenado em buffer ou impedir que outro programa altere o arquivo.
Declare recursos no cabeçalho do try
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
class Lines {
static void show(Path file) throws IOException {
try (BufferedReader in =
Files.newBufferedReader(file, StandardCharsets.UTF_8)) {
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
}
}
}
O cabeçalho abre o leitor. O corpo o usa, e Java o fecha quando o corpo termina normalmente, retorna ou lança uma exceção. Não é necessário um finally separado. Não há tratador aqui, portanto qualquer falha verificada ainda passa ao chamador por meio de throws IOException.
Um recurso deve implementar AutoCloseable. Essa interface declara close() e permite Exception; sua subinterface Closeable restringe a falha verificada declarada a IOException. Leitores, gravadores e Scanner atendem a esse requisito. Uma String não. Variáveis do cabeçalho são implicitamente final e estão disponíveis no corpo, não nos blocos catch ou finally dessa instrução. Java 9 e versões posteriores também permitem uma variável existente final ou efetivamente final: try (in) { ... }.
Feche na ordem inversa
Separe os recursos com pontos e vírgulas:
try (BufferedReader in = Files.newBufferedReader(source);
java.io.BufferedWriter out = Files.newBufferedWriter(target)) {
String line;
while ((line = in.readLine()) != null) {
out.write(line);
out.newLine();
}
}
Este é um bloco dentro de um método que declara IOException, com caminhos distintos source e target. Java abre in primeiro, depois out, e fecha out antes de in. Se a abertura de out falhar, o leitor já aberto ainda será fechado. Abrir um gravador no caminho de entrada truncaria essa entrada, portanto os caminhos devem ser diferentes para essa cópia direta.
O fechamento dos recursos ocorre antes das cláusulas catch e finally pertencentes à mesma instrução. Esses tratadores podem receber falhas da abertura, do uso ou do fechamento dos recursos.
Mantenha a falha principal visível
Suponha que o corpo lance uma exceção de registro e, em seguida, o fechamento do leitor lance uma IOException. Try-with-resources propaga a exceção do corpo e associa a falha de fechamento como suprimida. getSuppressed() a recupera, e o rastreamento exibe uma seção Suppressed:. A falha original do corpo permanece visível. Se o corpo tiver sucesso e apenas o fechamento falhar, a exceção de fechamento se propagará normalmente.
Com várias falhas durante o fechamento, Java ainda tenta os fechamentos restantes. Um simples finally { resource.close(); } pode, em vez disso, substituir uma falha pendente do corpo por uma falha de limpeza.
Use esse padrão para recursos de arquivo que pertencem ao seu código. Fechar um scanner sobre System.in também fecha a entrada de teclado do programa, impedindo leituras posteriores. Mantenha a responsabilidade pela entrada padrão compartilhada no nível do programa em vez de fechá-la em um método auxiliar.
Principais conclusões
- Try-with-resources fecha recursos abertos com sucesso em saídas normais e excepcionais.
- Somente objetos
AutoCloseablepodem ser recursos. - Os recursos são abertos da esquerda para a direita e fechados da direita para a esquerda.
- O fechamento precede os blocos catch e finally da mesma instrução.
- Uma falha do corpo permanece como principal; falhas posteriores de fechamento são suprimidas.
- O fechamento automático não substitui o tratamento pela regra de capturar ou declarar.
- Fechar um scanner também fecha sua fonte de entrada, se ela puder ser fechada.
5Leia e grave arquivos de texto
O processamento de arquivos conecta bytes externos aos objetos e resultados que seu programa usa. Leia linhas com um método adequado ao tamanho da entrada, valide os campos antes da conversão e grave com uma escolha consciente entre substituição e acréscimo ao final. Um relatório completo precisa de respostas distintas para um registro inválido e um arquivo inutilizável. Construa o resultado antes de salvá-lo e use uma saída temporária e uma movimentação atômica suportada quando um destino existente precisar ser protegido.
5.1 Leia linhas e transforme-as em objetos
A leitura fornece texto. A análise e conversão dão significado a esse texto: uma contagem, uma idade ou um objeto. Mantenha essas duas operações separadas para que um registro inválido não pareça uma falha de leitura do arquivo.
Escolha quanto manter na memória
| Método | Resultado e uso |
|---|---|
Files.readAllLines(path) | Uma lista com todas as linhas; conveniente para arquivos pequenos |
Files.readString(path) | Uma cadeia de caracteres que preserva os terminadores de linha |
BufferedReader.readLine() | Uma linha por vez; null sinaliza o fim |
Scanner.hasNextLine() / nextLine() | Leitura conveniente linha por linha |
Importe java.nio.file.Files e Path, além dos tipos de leitor ou coleção que você usar. Os métodos de texto de Files usam UTF-8 por padrão. Um BufferedReader deve ficar em try-with-resources e informa falhas de leitura com IOException. Ler uma linha por vez evita manter toda a entrada na memória, a menos que seu processamento armazene todos os registros depois.
Um scanner também precisa ser fechado e requer uma verificação adicional de falha:
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Scanner;
class ScanFile {
static void show(Path file) throws IOException {
try (Scanner sc = new Scanner(file, StandardCharsets.UTF_8)) {
while (sc.hasNextLine()) {
System.out.println(sc.nextLine());
}
if (sc.ioException() != null) throw sc.ioException();
}
}
}
A abertura pode lançar uma exceção diretamente. Durante a leitura, Scanner trata uma falha subjacente de entrada e saída como fim da entrada e a armazena; ioException() a disponibiliza. Sem essa verificação final, uma leitura parcial pode parecer bem-sucedida.
Conte as linhas físicas e depois analise e converta
Para as linhas de entrada “12”, “15”, “abc”, uma linha vazia e “9”, incremente o número da linha antes de decidir se uma linha em branco será ignorada. Converta cada linha não vazia com Integer.parseInt(line.trim()) dentro de seu próprio try. Informe “Line 3: not a number: abc” e continue. A soma válida é 36 e a contagem é 3, resultando em média 12,0. Calcule (double) sum / count para preservar um resultado fracionário e verifique primeiro se a contagem não é zero.
Verifique os campos antes de acessar por índice
Dados simples separados por vírgulas podem se tornar objetos. Aqui a primeira linha é um cabeçalho obrigatório; cada registro restante tem um nome não vazio e uma idade inteira:
String[] parts = line.split(",", -1);
if (parts.length != 2 || parts[0].isBlank() || parts[1].isBlank()) {
System.out.println("Line " + lineNumber + ": expected name and age");
continue;
}
try {
int age = Integer.parseInt(parts[1].trim());
people.add(new Person(parts[0].trim(), age));
} catch (NumberFormatException e) {
System.out.println("Line " + lineNumber + ": invalid age");
}
Este trecho do corpo de um laço pressupõe line, lineNumber, uma List<Person> chamada people e um construtor Person(String, int). Ignore o cabeçalho “name,age” antes dessa etapa de análise e conversão; caso contrário, “age” falhará na conversão numérica. Os registros “Ana,34”, “Ben,29” e “Chen,41” totalizam 104 anos e têm média de aproximadamente 34,67.
Um simples split(",") descarta campos vazios no final: “Eve,” produz apenas uma parte. O limite -1 mantém o segundo campo vazio para que a validação possa informá-lo. Sempre verifique o comprimento antes de parts[1]. A divisão por si só não trata vírgulas entre aspas, como no nome em “"Smith, Ana",34”; o formato CSV completo precisa de um analisador de CSV.
Principais conclusões
- Escolha métodos que leem o arquivo inteiro para entradas de tamanho gerenciável ou um laço de leitura para entradas grandes.
- Verifique
Scanner.ioException()após a leitura para detectar uma falha de leitura oculta. - Conte as linhas originais do arquivo mesmo quando linhas em branco ou registros forem ignorados.
- Verifique o número de campos e os valores obrigatórios antes de acessar por índice e converter.
- Ignore um cabeçalho antes de analisar e converter os registros.
- Uma divisão simples não consegue analisar campos CSV entre aspas.
5.2 Grave o texto completo e acrescente conteúdo de forma intencional
Abrir um arquivo de saída pode alterá-lo imediatamente. Escolha entre substituição e acréscimo ao final antes de abrir o gravador e termine fechando-o para que a saída armazenada em buffer não fique na memória.
Substitua ou acrescente ao final
Files.writeString(path, text) grava uma cadeia de caracteres. Files.write(path, lines) grava uma sequência iterável de linhas, adicionando o separador de linha do sistema após cada uma, incluindo a última. Com as opções padrão, ambos criam um arquivo ausente e truncam um existente.
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
class RunLog {
static void recordStart(Path log) throws IOException {
Files.writeString(log, "started" + System.lineSeparator(),
StandardCharsets.UTF_8,
StandardOpenOption.CREATE, StandardOpenOption.APPEND);
}
}
CREATE permite criar um novo arquivo; APPEND preserva o conteúdo antigo e adiciona ao final. APPEND sozinho falha se o arquivo estiver ausente. O acréscimo não insere um separador ausente antes do seu texto: se um arquivo existente terminar no meio de uma linha, os próximos caracteres continuarão essa linha.
O FileWriter mais antigo tem um indicador de acréscimo: new FileWriter("log.txt", StandardCharsets.UTF_8, true). Sem acréscimo, um novo FileWriter ou um PrintWriter criado com nome de arquivo também trunca um arquivo existente. Nunca abra um gravador que substitui o conteúdo em uma entrada que você ainda precisa ler.
Escolha um gravador e perceba as falhas
BufferedWriter oferece write e newLine() e informa falhas de gravação como exceções verificadas:
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Locale;
class ReportWriter {
static void write(Path file) throws IOException {
try (BufferedWriter out =
Files.newBufferedWriter(file, StandardCharsets.UTF_8)) {
out.write("Readings: 3");
out.newLine();
out.write(String.format(Locale.ROOT, "Average: %.2f", 3.0));
out.newLine();
}
}
}
O arquivo tem duas linhas: “Readings: 3” e “Average: 3.00”. Locale.ROOT fixa o ponto decimal. newLine(), println e %n usam o terminador de linha da plataforma; um \n literal grava LF em todos os sistemas.
Um PrintWriter oferece os convenientes print, println e printf, mas esses métodos registram falhas de entrada e saída em vez de lançá-las. checkError() descarrega o buffer e informa seu indicador de erro. Para verificar também falhas no fechamento final, mantenha acesso ao gravador e verifique após fechá-lo. Para código que precisa propagar falhas de gravação de forma confiável, use BufferedWriter ou os métodos de Files.
Complete o ciclo de gravação e leitura
Gravadores armazenam a saída em buffer. flush() envia o texto pendente adiante; close() descarrega o buffer e libera o arquivo. Try-with-resources garante que o fechamento seja tentado em toda saída, mas não pode fazer uma gravação em disco ter sucesso.
Para salvar uma pessoa, grave o nome, uma vírgula e a idade inteira, seguidos de um terminador de linha. Formate decimais com Locale.ROOT para que um Double.parseDouble posterior possa lê-los. Um diretório ancestral ausente não é criado pela abertura de um arquivo: use Files.createDirectories(folder) quando a intenção for criá-lo ou informe a falha. Uma gravação pode falhar após truncar o arquivo ou produzir uma saída parcial; use uma saída temporária e uma movimentação atômica quando o destino precisar ser protegido.
Principais conclusões
- A gravação padrão cria um arquivo ausente e trunca um existente.
- Use
CREATEcomAPPENDpara preservar o conteúdo antigo e permitir um novo arquivo de registro. - O fechamento descarrega a saída armazenada em buffer e libera o recurso.
PrintWriterregistra erros de gravação;checkError()os disponibiliza.BufferedWritere os métodos deFilespropagam falhas de entrada e saída.- Use UTF-8 e
Locale.ROOTpara um ciclo portátil de gravação e leitura de texto. - Gravar um arquivo não cria pastas ancestrais ausentes.
5.3 Construa um relatório sem ocultar falhas
Um processador robusto de arquivos precisa de dois níveis de recuperação. Um registro inválido pode ser ignorado e informado; uma falha ao ler ou salvar o arquivo interrompe a tarefa. Calcule um resultado completo antes de alterar seu destino.
Leia, valide, calcule e salve
O programa completo abaixo lê o cabeçalho opcional “date,temperature” seguido de registros simples com dois campos. As datas são identificadores não vazios; as temperaturas são números finitos em graus Celsius. Ele ignora e informa registros malformados, incluindo linhas em branco. A exceção verificada aninhada mantém problemas de registro separados de problemas de arquivo.
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.AtomicMoveNotSupportedException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.Locale;
public class TemperatureReport {
static class InvalidRecordException extends Exception {
InvalidRecordException(String message) { super(message); }
InvalidRecordException(String message, Throwable cause) {
super(message, cause);
}
}
static List<String> readLines(Path file) throws IOException {
return Files.readAllLines(file, StandardCharsets.UTF_8);
}
static double parseTemperature(String line, int lineNumber)
throws InvalidRecordException {
String[] parts = line.split(",", -1);
if (parts.length != 2 || parts[0].isBlank()
|| parts[1].isBlank()) {
throw new InvalidRecordException("Line " + lineNumber
+ ": expected a date label and a temperature");
}
try {
double value = Double.parseDouble(parts[1].trim());
if (!Double.isFinite(value)) {
throw new InvalidRecordException("Line " + lineNumber
+ ": temperature must be finite");
}
return value;
} catch (NumberFormatException e) {
throw new InvalidRecordException("Line " + lineNumber
+ ": not a number: " + parts[1], e);
}
}
static String summarize(List<String> lines) {
int count = 0;
int skipped = 0;
double sum = 0;
double min = Double.POSITIVE_INFINITY;
double max = Double.NEGATIVE_INFINITY;
for (int i = 0; i < lines.size(); i++) {
String line = lines.get(i);
if (i == 0 && line.equals("date,temperature")) continue;
try {
double value = parseTemperature(line, i + 1);
sum += value;
count++;
min = Math.min(min, value);
max = Math.max(max, value);
} catch (InvalidRecordException e) {
skipped++;
System.err.println(e.getMessage());
}
}
if (count == 0) {
return String.format(Locale.ROOT,
"No valid readings%nSkipped lines: %d%n", skipped);
}
return String.format(Locale.ROOT,
"Valid readings: %d%nAverage (°C): %.2f%n"
+ "Minimum (°C): %.2f%nMaximum (°C): %.2f%n"
+ "Skipped lines: %d%n",
count, sum / count, min, max, skipped);
}
static void writeSummary(Path file, String text) throws IOException {
Path target = file.toAbsolutePath();
Path temp = Files.createTempFile(target.getParent(), "report-", ".tmp");
try {
Files.writeString(temp, text, StandardCharsets.UTF_8);
Files.move(temp, target, StandardCopyOption.ATOMIC_MOVE);
} catch (IOException e) {
try {
Files.deleteIfExists(temp);
} catch (IOException cleanup) {
e.addSuppressed(cleanup);
}
throw e;
}
}
public static void main(String[] args) {
Path input = Path.of("readings.csv");
Path output = Path.of("summary.txt");
try {
List<String> lines = readLines(input);
String report = summarize(lines);
writeSummary(output, report);
System.out.println("Saved: " + output.toAbsolutePath());
} catch (NoSuchFileException e) {
System.err.println("File or folder not found: " + e.getFile());
} catch (AtomicMoveNotSupportedException e) {
System.err.println("Could not save atomically: "
+ output.toAbsolutePath());
} catch (IOException e) {
System.err.println("Could not process " + input.toAbsolutePath()
+ " or save " + output.toAbsolutePath() + ": " + e.getMessage());
}
}
}
Acompanhe uma execução
Use estas cinco linhas de entrada sem cabeçalho:
2026-03-01,4.5
2026-03-02,6.0
2026-03-03,abc
2026-03-04,-1.5
missing comma
As linhas 1, 2 e 4 produzem três leituras válidas. A soma é 9,0; a média é 3,00 °C, o mínimo é -1,50 °C e o máximo é 6,00 °C. As linhas 3 e 5 produzem mensagens de diagnóstico, e o relatório registra duas linhas ignoradas. O tratador de análise e conversão fica dentro do laço, portanto cada registro inválido permite que os registros posteriores sejam alcançados. Atualizar os totais somente após uma análise e conversão bem-sucedida mantém os valores rejeitados fora deles.
Double.parseDouble aceita cadeias especiais como “NaN” e “Infinity”. Double.isFinite as rejeita aqui porque elas não podem servir como temperaturas medidas comuns. Um arquivo vazio, um arquivo com apenas o cabeçalho ou registros todos inválidos chegam ao ramo de contagem zero antes da divisão ou do uso do mínimo e máximo iniciais.
Proteja o destino
A leitura e o cálculo terminam antes do início da gravação. Files.writeString abre e fecha seu próprio arquivo, mas pode falhar depois de gravar parte dele. O programa, portanto, grava em um arquivo temporário na pasta de destino, fecha-o e solicita ATOMIC_MOVE. A movimentação torna o resultado concluído visível em uma única operação do sistema de arquivos, quando suportada.
A substituição atômica de um destino existente depende da implementação. O programa informa uma movimentação ou substituição não suportada e nunca tenta novamente com uma movimentação não atômica. Uma falha de limpeza é associada à exceção original em vez de substituí-la. A visibilidade atômica não garante a preservação dos dados após uma perda de energia.
Verificar Files.exists(input) antecipadamente não pode garantir a leitura posterior: um arquivo pode desaparecer ou se tornar inacessível após a verificação. Trate a operação efetiva. Antes de confiar em um processador, teste uma entrada ausente, pastas de saída ausentes, arquivos vazios e com apenas cabeçalho, terminadores CRLF, texto acentuado e registros malformados. Mensagens ao usuário devem indicar o caminho que falhou; a depuração de um encapsulador também precisa de sua causa original e de seu rastreamento da pilha.
Principais conclusões
- Trate falhas em registros dentro do laço e falhas no processamento do arquivo inteiro fora dele.
- Valide um registro completo antes de atualizar contagens ou totais.
- Verifique se há zero registros válidos antes de calcular uma média.
- Conclua a leitura e o cálculo antes de abrir a saída.
- Grave e feche um arquivo temporário e solicite uma movimentação atômica para proteger o destino.
- Informe a substituição atômica não suportada em vez de recorrer silenciosamente a outra opção.
- Mantenha as causas originais e as falhas de limpeza disponíveis para diagnóstico.
Exercícios resolvidos de Exceções em Java
1Acompanhe uma falha até sua causa
11 passos
- 1IntroduçãoUm programa pode compilar e ainda falhar
Um valor de entrada pode fazer código Java válido falhar durante a execução. O objeto de exceção informa que tipo de problema ocorreu, e o rastreamento da pilha mostra quais chamadas de método estavam ativas.
Acompanhe primeiro uma conversão inteira malsucedida. Depois, use as mesmas regras de herança que permitem usar objetos de subclasse como objetos de superclasse para decidir o que o compilador exige que você trate.
- 2ExemploObserve a conversão ser interrompida
Um método
loadCountexecuta estas instruções:System.out.print("start "); int count = Integer.parseInt("eight"); System.out.print("finish");Ele exibe
starte depois lançaNumberFormatException. A atribuição não é concluída, efinishé ignorado. Um tratador compatível pode assumir o controle, mas a instrução que falhou não é retomada após a recuperação. - 3ExplicaçãoAcompanhe as chamadas ativas
Suponha que
maintenha chamadoloadCount, que chamouInteger.parseInt. Essas chamadas fazem parte da pilha de chamadas. A exceção se propaga para fora quando um método não tem um tratador compatível.parseIntfalha primeiro,loadCountnão consegue concluir seu trabalho normal e o chamador tem a chance de tratar a falha. Se ela sair demainsem tratamento, Java informa a exceção e a thread principal termina. - 4ExemploEncontre seu primeiro registro de ativação
Um rastreamento pode incluir estes registros da aplicação após os registros da biblioteca de Java:
at Counts.loadCount(Counts.java:14) at Counts.main(Counts.java:5)Examine primeiro a linha 14: essa é a chamada em seu código mais próxima do ponto de detecção. A linha 5 informa onde
loadCountfoi chamado. A primeira linha da exceção fornece sua classe e mensagem; não confunda o registro do chamador abaixo com a instrução que primeiro usou o texto inválido. - 5DesafioIdentifique a saída ignorada
Um método auxiliar exibe
A, chamaInteger.parseInt("q2")e depois exibiriaB. Seu chamador capturaNumberFormatExceptione exibeC. Quais letras são exibidas e por quê?---reveal---
Ae depoisC. A conversão lança uma exceção antes deB; a propagação leva a falha ao tratador compatível do chamador. As instruções restantes do método auxiliar são abandonadas, portanto a recuperação não retorna para exibirB. - 6DicaOlhe além da instrução detectada
A instrução em que uma falha é detectada pode estar usando um valor inválido criado anteriormente. Uma falha de referência nula indica que você deve investigar onde essa referência deveria ter recebido um objeto.
Use
getMessage()para obter o texto de diagnóstico eprintStackTrace()para a cadeia de chamadas. Uma mensagem pode sernull; uma seçãoCaused by:fornece outra exceção preservada dentro de um encapsulador. - 7ExplicaçãoUse a cadeia de superclasses
Throwableé a classe base dos objetos que podem ser lançados. Seus ramos principais sãoErroreException;RuntimeExceptionestá abaixo deException.RuntimeException,Errore todas as subclasses de ambos são não verificados. Outras subclasses deThrowablesão verificadas. Ambas as categorias falham durante a execução; “verificada” descreve a verificação do tratamento pelo compilador, não um momento diferente em que a exceção é lançada. - 8ExemploCompare um analisador e um leitor de arquivos
NumberFormatExceptionestendeIllegalArgumentException, que estendeRuntimeException, portanto uma chamada deInteger.parseIntnão exige um tratador obrigatório.IOExceptionestendeExceptionfora desse ramo. Uma chamada deFiles.readStringdeve capturar sua possívelIOExceptionou declará-la comthrows. Um arquivo pode falhar por razões externas mesmo quando o código que o chama está correto. - 9DesafioClassifique uma falha desconhecida
BadRecordExceptionestendeExceptiondiretamente. Um método auxiliar declara que pode lançar esse tipo. O que seu chamador deve fazer e quando essa obrigação é verificada?---reveal---
Capturá-la ou declarar um tipo verificado aplicável na declaração do método chamador. O compilador impõe essa obrigação porque a classe está fora dos ramos não verificados. O sucesso de uma execução específica não elimina a exigência na declaração.
- 10DesafioExplique um tratador surpreendentemente abrangente
Um bloco de leitura de arquivo captura
Exceptione exibe “Problema no arquivo”. Em vez disso, ele falha com umaNullPointerExceptioncausada por um defeito. O tratador receberá a exceção, e essa mensagem é confiável?---reveal---
Sim:
NullPointerExceptionestendeRuntimeException, que estendeException. A mensagem é enganosa porque essa falha é um defeito no código, não uma evidência de problema no arquivo. Leia o rastreamento e restrinja o tratador esperado às falhas que ele pode explicar. - 11RecapitulaçãoEscolha a próxima ação de depuração
Comece a investigação de uma falha por sua classe, mensagem e primeiro registro de ativação da aplicação. Acompanhe os chamadores e a origem dos valores inválidos quando a instrução detectada, sozinha, não explicar a causa.
Depois, verifique a herança antes de escolher o tratamento: falhas verificadas exigem uma decisão visível ao compilador; defeitos não verificados ainda precisam de correção. Evite que tratadores abrangentes disfarcem um tipo de problema como outro.
2Acompanhe caminhos de recuperação e limpeza
12 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoDecida o que deve acontecer em seguida
- 2ExemploRecupere a execução após toda a instrução
- 3DicaFaça a nova tentativa ler um novo texto
- 4DesafioCorrija o scanner preso
- 5ExplicaçãoDê uma resposta própria a uma falha específica
- 6ExemploDeixe o laço continuar
- 7DesafioMova o limite da região protegida
- 8Ideia-chaveCompartilhe respostas sem sobrepor tipos
- 9ExplicaçãoA limpeza é executada antes da saída
- 10DesafioAcompanhe uma falha sem tratador compatível
- 11DesafioImpeça que a limpeza oculte uma falha que exige nova tentativa
- 12RecapitulaçãoAcompanhe a próxima instrução alcançável
3Rejeite uma solicitação sem danificar o estado
11 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoPreserve um objeto utilizável
- 2ExemploValide antes da subtração
- 3ExplicaçãoSepare throw da declaração
- 4DesafioEscolha a falha padrão adequada
- 5ConexãoUma sobrescrita mantém as promessas aos chamadores
- 6ExemploDê ao estoque insuficiente seu próprio tipo
- 7ExemploMantenha a solicitação malsucedida separada
- 8DesafioDecida qual estado permanece
- 9ExplicaçãoPreserve a falha de conversão original
- 10DesafioPasse uma falha de arquivo por um método com restrições
- 11RecapitulaçãoProjete uma exceção que o chamador possa usar
4Abra o texto correto e feche-o com segurança
12 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoLocalização e tempo de vida são importantes
- 2ExemploResolva a partir do diretório de trabalho
- 3ExplicaçãoDecodifique com a codificação usada na gravação
- 4DicaRemova um terminador de linha completo
- 5DesafioFaça um decimal sobreviver ao ciclo de gravação e leitura
- 6ExplicaçãoDeclare um recurso para fechar
- 7ConexãoUse o contrato de fechamento
- 8ExemploInverta a ordem de abertura
- 9DesafioAcompanhe uma segunda abertura malsucedida
- 10Ideia-chaveMantenha uma falha do corpo como a principal informada
- 11DesafioSepare a falha de dados da falha de limpeza
- 12RecapitulaçãoExamine uma operação de arquivo em ordem
5Transforme leituras em um relatório confiável
16 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoUm relatório precisa de mais que cálculos corretos
- 2ExplicaçãoEscolha como as linhas serão recebidas
- 3ExemploDefina o registro antes da análise e conversão
- 4ExemploValide antes de usar o segundo campo
- 5DesafioLocalize o registro rejeitado
- 6ExplicaçãoEscolha entre substituir e acrescentar ao final
- 7ExemploGrave uma linha de relatório portátil
- 8DicaIdentifique uma gravação malsucedida
- 9DesafioMantenha os registros antigos e novos
- 10ConexãoRecupere a execução em dois níveis diferentes
- 11ExemploAtualize os totais somente após a validação
- 12DesafioTrate um valor que é convertido, mas não serve
- 13ExplicaçãoConclua a saída antes de substituir o destino
- 14DicaMantenha visível a falha de salvamento
- 15DesafioEscolha o que pode ser informado com segurança
- 16RecapitulaçãoRevise o processador por caminho de falha
Questões de Exceções em Java
Conjunto 1: Acompanhe falhas e escolha uma recuperação útil10 Questões de Prática
Questão 1 de 10
DataProblem estende Exception diretamente. Qual obrigação um método tem ao chamar um método auxiliar declarado com throws DataProblem?Mostrar respostaOcultar resposta
DataProblem é verificada porque estende Exception fora do ramo de RuntimeException. O código chamador deve capturá-la ou declarar um tipo verificado aplicável. O compilador verifica a possibilidade declarada, mesmo que uma chamada específica seja bem-sucedida.Questão 2 de 10
values[5]?Mostrar respostaOcultar resposta
ArrayIndexOutOfBoundsException nesse acesso. Contar cinco elementos não torna o índice 5 válido: o quinto elemento está no índice 4.Questão 3 de 10
Quais letras são exibidas, em ordem?
System.out.print("P");
try {
int n = Integer.parseInt("7q");
System.out.print("Q");
} catch (NumberFormatException e) {
System.out.print("R");
}
System.out.print("S");
Mostrar respostaOcultar resposta
NumberFormatException antes da instrução que exibe Q. O tratador compatível exibe R, depois a execução continua após a instrução e exibe S. A instrução ignorada não é executada após a recuperação, portanto PQRS não pode ser a saída.Questão 4 de 10
NoSuchFileException ou outra IOException. Qual ordem de captura dá a cada uma sua própria resposta?Mostrar respostaOcultar resposta
NoSuchFileException estende IOException, portanto seu tratador específico deve aparecer primeiro. Colocar IOException primeiro já capturaria toda exceção de arquivo ausente e tornaria o tratador posterior inalcançável. Uma captura múltipla também não pode combinar esses tipos relacionados.Questão 5 de 10
O que a chamada de pick() exibe e retorna?
static int pick() {
try {
return 8;
} finally {
System.out.print("done");
}
}
Mostrar respostaOcultar resposta
finally antes de entregar esse valor ao chamador. Portanto, ele exibe done e retorna 8. Um retorno dentro de try não ignora a limpeza; somente uma transferência de controle concorrente da limpeza substituiria esse resultado.Questão 6 de 10
Mostrar respostaOcultar resposta
IllegalArgumentException descreve a falha. IllegalStateException descreveria uma chamada proibida pelo estado atual do objeto. Nenhuma operação de análise e conversão é mencionada, portanto um argumento numérico, por si só, não faz disso uma falha de formato numérico.Questão 7 de 10
/work/app. Ele cria Path.of("data", "levels.txt"). Qual localização absoluta esse caminho relativo identifica?Mostrar respostaOcultar resposta
/work/app para /work/app/data/levels.txt. Java não insere uma pasta de código-fonte. Colocar o arquivo ao lado do código-fonte só funcionaria se essa fosse a localização indicada pelo caminho resolvido.Questão 8 de 10
a é aberto, mas a abertura do recurso b lança uma exceção. Ambos são declarados no mesmo cabeçalho de try-with-resources, nessa ordem. O fechamento de a também lança uma exceção. Qual falha chega ao chamador?Mostrar respostaOcultar resposta
b falha, Java ainda fecha a, que já está aberto. A falha de abertura permanece como principal, e a falha posterior de fechamento é associada como suprimida. Escolher a falha de fechamento como principal confunde try-with-resources com a limpeza manual que pode sobrescrever uma falha anterior.Questão 9 de 10
BufferedReader chegou ao fim de seu arquivo. O que a próxima chamada de readLine() retorna?Mostrar respostaOcultar resposta
BufferedReader.readLine() retorna null quando não restam caracteres para formar outra linha. Uma cadeia vazia representa uma linha em branco real, portanto usá-la como marcador de fim interromperia a leitura cedo demais. Terminadores de linha são removidos das linhas retornadas e não são marcadores de fim de arquivo.Questão 10 de 10
Files.writeString preserve o texto existente e adicione novo texto ao final?Mostrar respostaOcultar resposta
APPEND grava após o conteúdo existente, e CREATE permite criar um arquivo ausente. Usar apenas APPEND falha quando o arquivo de registro não existe. TRUNCATE_EXISTING apagaria o conteúdo existente, enquanto CREATE_NEW rejeita um caminho que já existe.Conjunto 2: Aplique contratos a registros e à saída de arquivos10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
Um rastreamento começa com estes registros de ativação. Qual linha na classe do aluno deve ser examinada primeiro?
java.lang.NumberFormatException: For input string: "six"
at java.base/java.lang.NumberFormatException.forInputString(...)
at java.base/java.lang.Integer.parseInt(...)
at Importer.readCount(Importer.java:18)
at Importer.main(Importer.java:6)
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
AmountProblem estende IllegalArgumentException. Como ela é classificada?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
InputMismatchException de Scanner.nextInt(), exibe uma mensagem e chama nextInt() novamente de imediato. A próxima unidade de entrada é “muitos”. Por que o laço continua falhando?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
void load() throws IOException. Uma implementação precisa declarar uma falha de arquivo ausente. Qual declaração verificada é permitida em sua sobrescrita?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
remove rejeita solicitações maiores que o estoque atual antes de alterar o mapa. Chamadas removem 6 e depois solicitam 14; a segunda falha é encapsulada com sua causa e capturada pelo chamador. Que estoque e informações de diagnóstico permanecem?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
Double.parseDouble("6,25") é executado em um computador que usa configurações regionais alemãs?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
line.split(",") e line.split(",", -1)?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
PrintWriter, mas um disco cheio impede que o texto seja salvo. O que ele deve usar para detectar o erro registrado pelo gravador?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Conjunto 3: Acompanhe falhas que interagem e a limpeza10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
Qual valor é exibido?
int count;
try {
count = Integer.parseInt("bad");
} catch (NumberFormatException e) {
count = 4;
}
System.out.println(count + 2);
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
NumberFormatException quando capturada por um tratador de superclasse?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
Qual valor chega à instrução final de impressão?
int total = 0;
try {
for (String text : new String[] {"8", "bad", "3"}) {
try {
total += Integer.parseInt(text);
} catch (NumberFormatException e) {
throw new IllegalStateException("record", e);
}
}
} catch (IllegalStateException e) {
total += 2;
}
System.out.println(total);
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
O que result() faz?
static int result() {
try {
throw new IllegalArgumentException("bad");
} finally {
return 9;
}
}
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
NumberFormatException e. Sua InvalidRecordException personalizada tem construtores que recebem apenas uma mensagem ou uma mensagem e uma causa. Como ele deve adicionar “Line 8” preservando o rastreamento original?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
Files.readString(path).split("\n") e depois Integer.parseInt em cada trecho não vazio. Por que a conversão de um trecho que contém os algarismos “27” pode falhar?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
a e b são abertos com sucesso nessa ordem. O corpo lança E; o fechamento de b lança F; o fechamento de a lança G. O que chega ao catch associado a essa instrução try-with-resources?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
Files.exists e depois lida com um scanner. Seu laço termina após apenas alguns registros porque o leitor subjacente falhou, e o programa começa a salvar imediatamente. O que deve mudar para impedir que essa entrada parcial seja tratada como sucesso?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Conjunto 4: Diagnostique e melhore um processador completo10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
O que é exibido antes de a exceção sair de main, e qual é o primeiro registro de ativação da aplicação em seu rastreamento?
public class Counter {
static int read() {
return Integer.parseInt("9z");
}
static void show() {
System.out.print("L");
System.out.print(read());
System.out.print("M");
}
public static void main(String[] args) {
show();
System.out.print("N");
}
}
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
catch (NumberFormatException | IllegalArgumentException e). Por que essa captura múltipla não compila?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
O que choose() exibe e retorna?
static int choose() {
int value = 5;
try {
return value;
} finally {
value = 12;
System.out.print(value);
}
}
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
ReaderTask declara String read() throws IOException. A classe FixedTask a implementa com public String read() e sem declaração de exceção verificada. A variável task tem tipo ReaderTask e se refere a um FixedTask. O que o código que chama task.read() deve fazer?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
IOException. Qual encapsulador padrão preserva essa causa e apresenta uma falha não verificada?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
close() então lança IOException, e o catch associado retorna 2; seu bloco finally exibe “closed” sem lançar uma exceção. O que o método faz?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
Double.parseDouble em computadores com qualquer configuração regional. Qual abordagem de gravação atende a esse formato?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Travou em uma questão sua? Ajuda com Tarefas
Termos-Chave
A
Acréscimo ao final do arquivo
Análise e conversão de texto
Arquivo temporário
B
Bloco finally
return chegue ao chamador.Bloco try
C
Caminho absoluto
toAbsolutePath() mostra o caminho absoluto usado para diagnosticar um arquivo colocado na pasta errada.Caminho relativo
data/counts.txt pode identificar um arquivo diferente quando o programa é iniciado em outra pasta.Campo
Captura múltipla
Causa
InvalidRecordException pode ser a NumberFormatException lançada por seu campo numérico.Classe BufferedReader
BufferedReader processa uma entrada grande até que readLine() retorne null no final.Classe BufferedWriter
BufferedWriter grava uma linha de relatório e depois usa newLine() para adicionar o terminador de linha da plataforma.Classe Error
OutOfMemoryError pertence a Error; capturar entradas inválidas comuns não resolve o esgotamento do heap.Classe PrintWriter
PrintWriter pode formatar uma média com printf, mas o retorno bem-sucedido dessa chamada não prova que o salvamento teve sucesso.Classe RuntimeException
NumberFormatException chega a RuntimeException por meio de sua superclasse IllegalArgumentException.Classe Scanner
Scanner de arquivo precisa de uma verificação de ioException() após seu laço para que uma leitura malsucedida não pareça bem-sucedida.Classe Throwable
Throwable por meio de Exception, portanto Java pode lançá-la e capturá-la.Cláusula catch
NumberFormatException pode pedir outro número depois que o usuário digitar “muitos”.Cláusula throws
throws IOException permite que um método auxiliar de arquivo informe a falha a um chamador capaz de se recuperar.Codificação de caracteres
Configuração regional
D
Descarga do buffer
Diretório de trabalho
/work/app como diretório de trabalho, data/counts.txt aponta para dentro de /work/app/data.E
Encadeamento de exceções
Exceção
Exceção ArithmeticException
ArithmeticException na divisão.Exceção IllegalArgumentException
IllegalArgumentException quando sua quantidade obrigatoriamente positiva é fornecida como -2.Exceção IllegalStateException
IllegalStateException quando o código tenta adicionar outro item a ele.Exceção InputMismatchException
nextInt() lança InputMismatchException ao encontrar “vários” e deixa essa unidade de entrada disponível para ser descartada.Exceção não verificada
Exceção NullPointerException
name.trim() quando name é null lança NullPointerException antes que qualquer texto sem espaços ao redor seja retornado.Exceção NumberFormatException
Integer.parseInt("blue") lança NumberFormatException porque o texto não pode representar um inteiro.Exceção personalizada
Exceção suprimida
Exceção UncheckedIOException
IOException pode repassar uma falha de arquivo usando UncheckedIOException.Exceção verificada
IOException é uma exceção verificada, portanto um método auxiliar de leitura de arquivos deve capturá-la ou declará-la.F
Falha em um registro
Falha imediata
Falha no processamento do arquivo inteiro
H
Hierarquia de exceções
I
Instrução try com recursos
Interface AutoCloseable
AutoCloseable pode exibir seu nome quando a limpeza automática chama close().Interface Closeable
BufferedReader implementa Closeable, portanto pode ser declarado em try-with-resources.Interface Path
Path.of("data", "counts.txt") constrói um Path sem testar se a pasta de dados existe.L
Limpeza
Linha de cabeçalho
M
Mascaramento de exceção
finally pode causar mascaramento de exceção ao descartar uma falha lançada no bloco try.Memória intermediária
Movimentação atômica
O
Ordem das cláusulas catch
NoSuchFileException antes de IOException quando cada uma precisa de uma mensagem separada.P
Palavra-chave throw
throw antes da atribuição ao campo rejeita uma capacidade inválida enquanto preserva o valor anterior do campo.Pilha de chamadas
main chama load, que chama parse, a pilha de chamadas registra as três chamadas de método ativas.Propagação
R
Rastreamento da pilha
Recuperação
Recurso
Região protegida
Regra de capturar ou declarar
Files.readString, mesmo quando o arquivo que ele lê existe.Retorno pendente
finally não reavalia a expressão de um retorno pendente.T
Terminador de linha
BufferedReader.readLine() é removido antes que o método retorne o texto da linha.Tratador inalcançável
IOException primeiro cria um tratador inalcançável se NoSuchFileException for capturada depois.Truncamento
Files.writeString padrão causa truncamento, portanto uma falha posterior de gravação pode deixar um resultado incompleto.U
UTF-8
V
Valores separados por vírgulas
- 1Primeiros programas em Java
- 2Condições e laços em Java
- 3Métodos em Java
- 4Listas e vetores em Java
- 5Classes e objetos em Java
- 6Objetos e referências em Java
- 7HashMaps e coleções em Java
- 8Herança, interfaces e polimorfismo em Java
- 9Exceções em Java
- 10Pacotes e testes unitários em Java
- 11Genéricos e expressões lambda em Java
Sobre esta aula
Crie seus próprios Materiais de Estudo
Transforme suas anotações, slides e documentos em Guias de Estudo, Questões de Prática, Flashcards e mais 6 ferramentas.