• Nenhum resultado encontrado

Capturando Exceções

No documento Java Interfaces Gráficas e Banco de Dados (páginas 46-52)

Para capturar exceções usa-se um bloco try...cath, com a seguinte construção: try {

<Código que pode gerar erro> }

catch(TipoExceção_1 e) {

<Manipulador da exceção tipo 1> }

...

catch(TipoExceção_n e) {

<Manipulador da exceção tipo n> }

finally {

<Código finalizador> }

Dentro do trecho try coloca-se o código que será executado e verificado por um determinado erro. Se uma exceção ocorrer, ela será de um determinado tipo, e conforme o tipo, a execução será desviada para um trecho catch que trata esse tipo de exceção. Pode- se ter um ou mais trechos catch, conforme a necessidade.

 Em um erro de programação;  Em um erro interno do Java.

Se ocorrer um dos dois primeiros casos, então o programador deverá informar a quem usar o método que ele levanta uma exceção. Caso contrário, se não tiver nenhum mecanismo para tratar essas exceções, o programa termina a execução.

class Animation { ...

public Image loadImage(String s) throws IOException { ...

} }

Se o método pode lançar mais de uma exceção, separa-se por vírgula:

class Animation { ...

public Image loadImage(String s) throws EOFException, MalFormedURLException {

... } }

Não se deve anunciar (throws) erros internos do Java (derivadas de Error) nem erros em tempo de execução (RuntimeException), porque estão fora do alcance do programador. Essas exceções são chamadas não verificadas (unchecked).

As exceções não verificadas não podem ser tratadas, e devem ser evitadas no programa, através de verificações. Um método precisa declarar todas as exceções verificadas que ele pode levantar.

4.3 Levantar uma Exceção

Para um método levantar uma exceção, é usado o comando throw. Só se pode

levantar uma exceção se ela foi declarada no cabeçalho do método (ou uma superclasse). Exemplo:

throw new EOFException();

Ou, se preferir:

EOFException e = new EOFException();

throw e;

E para juntar tudo que foi visto nesta sessão:

String lerDados(BufferedReader ent) throws EOFException { ...

while (...) {

if (ch == -1) // encontrou EOF throw new EOFException(); }

}

A EOFException também tem um outro construtor, que recebe uma string, que serve para descrever a condição do erro mais detalhadamente. Exemplo:

throw new EOFException(“Conteúdo completo recebido.”);

4.4 Criar Novas Exceções

Para criar uma nova classe de exceção basta criar a classe e derivá-la de Exception ou de qualquer uma de suas subclasses.

class ExecucaoTamanhoArquivo extends IOException { public ExecucaoTamanhoArquivo() { }

public ExecucaoTamanhoArquivo(String str) { super(str);

} }

Agora pode-se usá-la normalmente nos programas:

String lerDados(BufferedReader ent) throws ExecucaoTamanhoArquivo { ...

while (...) {

if (ch == -1) // encontrou EOF

throw new ExecucaoTamanhoArquivo(); }

}

4.5 Capturando Exceções

Para capturar exceções usa-se um bloco try...cath, com a seguinte construção: try {

<Código que pode gerar erro> }

catch(TipoExceção_1 e) {

<Manipulador da exceção tipo 1> }

...

catch(TipoExceção_n e) {

<Manipulador da exceção tipo n> }

finally {

<Código finalizador> }

Dentro do trecho try coloca-se o código que será executado e verificado por um determinado erro. Se uma exceção ocorrer, ela será de um determinado tipo, e conforme o tipo, a execução será desviada para um trecho catch que trata esse tipo de exceção. Pode- se ter um ou mais trechos catch, conforme a necessidade.

O trecho finally é usado quando se deseja, por exemplo, liberar um recurso reservado por um código que gerou exceção. O trecho de código que estiver aí dentro sempre será executado, seja uma exceção tratada (catch) ou não. A cláusula finally pode ser usada mesmo sem o catch, assim, se uma exceção foi levantada, o trecho finally é executado e a exceção é relevantada.

Graphics g = image.getGraphics();

try {

// código que pode gerar erros }

catch(IOException e) { // tratamento de erros }

finally {

// libera recursos, mesmo se nenhuma exceção for levantada g.dispose();

}

Exercícios de Fixação 4 – Tratamento de Erros

Qual a diferença entre lançar uma exceção e capturar uma exceção?

Atividade 1 – GUI em Java

1. Faça uma classe executável que receba por meio da linha de comando do programa (prompt) dois números e um operador aritmético ( + , - , x , / ), informe o resultado da operação. Atenção: não é possível divisão por zero. Então, lance uma exceção caso isso ocorra.

2. Faça uma classe executável que receba por meio da linha de comando do programa (prompt) um número natural (de 1 a 10) e informe a sua tabuada. Atenção: Se não informado, assuma o valor 7. Então, utilize a cláusula finally em sua solução.

3. Crie uma classe de exceção que implemente o método toString() e retorne a mensagem “Impossível converter. Favor informar apenas dígitos na entrada de dados”

4. Crie uma classe que implemente o método retornaDouble(String) que lança a exceção implementada no enunciado 3 caso o String de entrada seja vazia.

5. Faça uma aplicação Java com uma interface que possibilite a digitação de um número e que mostre em uma mensagem (JOptionPane) com resultado da multiplicação deste número por 5. Utilize try-catch para tratar a exceção por meio do método de conversão de String para double implementado no enunciado 4 para tratar a entrada de dados.

Atividade 2 – GUI em Java (complementar)

1. Defina a classe ContaCorrente contendo os atributos número da conta, nome do cliente e saldo para lançar exceções (definidas por você) quando a conta é construída com saldo negativo e quando se saca uma quantidade maior que o saldo atual.

2. Faça uma aplicação Java com uma interface que possibilite a digitação de informações para instanciar objetos da classe ContaCorrente (criada no enunciado anterior) e armazenar num ArrayList.

3. Faça uma aplicação Java com uma interface que possibilite informar o número de uma conta corrente e o valor com dois botões (JButton), sendo um para depósito e outro para saque. O botão de saque deverá lançar uma exceção para tratar possível saldo negativo em caso de saque de valores superiores ao saldo atual da conta.

4. Defina uma classe MyInput, contendo métodos estáticos abaixo (todos os métodos devem retornar o tipo especificado), de forma que exceções sejam lançadas caso um valor incorreto tenha sido fornecido pelo usuário.

a. getInt para leitura de um inteiro, com parâmetros que representem os valores mínimo e máximo aceitos.

b. getFloat para leitura de um flutuante, com parâmetros que representem os valores mínimo e máximo aceitos.

O trecho finally é usado quando se deseja, por exemplo, liberar um recurso reservado por um código que gerou exceção. O trecho de código que estiver aí dentro sempre será executado, seja uma exceção tratada (catch) ou não. A cláusula finally pode ser usada mesmo sem o catch, assim, se uma exceção foi levantada, o trecho finally é executado e a exceção é relevantada.

Graphics g = image.getGraphics();

try {

// código que pode gerar erros }

catch(IOException e) { // tratamento de erros }

finally {

// libera recursos, mesmo se nenhuma exceção for levantada g.dispose();

}

Exercícios de Fixação 4 – Tratamento de Erros

Qual a diferença entre lançar uma exceção e capturar uma exceção?

Atividade 1 – GUI em Java

1. Faça uma classe executável que receba por meio da linha de comando do programa (prompt) dois números e um operador aritmético ( + , - , x , / ), informe o resultado da operação. Atenção: não é possível divisão por zero. Então, lance uma exceção caso isso ocorra.

2. Faça uma classe executável que receba por meio da linha de comando do programa (prompt) um número natural (de 1 a 10) e informe a sua tabuada. Atenção: Se não informado, assuma o valor 7. Então, utilize a cláusula finally em sua solução.

3. Crie uma classe de exceção que implemente o método toString() e retorne a mensagem “Impossível converter. Favor informar apenas dígitos na entrada de dados”

4. Crie uma classe que implemente o método retornaDouble(String) que lança a exceção implementada no enunciado 3 caso o String de entrada seja vazia.

5. Faça uma aplicação Java com uma interface que possibilite a digitação de um número e que mostre em uma mensagem (JOptionPane) com resultado da multiplicação deste número por 5. Utilize try-catch para tratar a exceção por meio do método de conversão de String para double implementado no enunciado 4 para tratar a entrada de dados.

Atividade 2 – GUI em Java (complementar)

1. Defina a classe ContaCorrente contendo os atributos número da conta, nome do cliente e saldo para lançar exceções (definidas por você) quando a conta é construída com saldo negativo e quando se saca uma quantidade maior que o saldo atual.

2. Faça uma aplicação Java com uma interface que possibilite a digitação de informações para instanciar objetos da classe ContaCorrente (criada no enunciado anterior) e armazenar num ArrayList.

3. Faça uma aplicação Java com uma interface que possibilite informar o número de uma conta corrente e o valor com dois botões (JButton), sendo um para depósito e outro para saque. O botão de saque deverá lançar uma exceção para tratar possível saldo negativo em caso de saque de valores superiores ao saldo atual da conta.

4. Defina uma classe MyInput, contendo métodos estáticos abaixo (todos os métodos devem retornar o tipo especificado), de forma que exceções sejam lançadas caso um valor incorreto tenha sido fornecido pelo usuário.

a. getInt para leitura de um inteiro, com parâmetros que representem os valores mínimo e máximo aceitos.

b. getFloat para leitura de um flutuante, com parâmetros que representem os valores mínimo e máximo aceitos.

c. getChar para leitura de um caractere, com um parâmetro do tipo String contendo um conjunto de caracteres aceitos.

5. Faça uma classe executável Java que teste entradas de dados para cada um dos métodos implementados no enunciado 4 e trate possíveis exceções (problemas de conversão com a estrutura try-catch).

5. Controle de entrada (I/O)

Exercício de nivelamento – I/O

Você já desenvolveu alguma aplicação que utilizou manipulou arquivos em disco? Em que linguagem? Trabalhou com gravação de objetos? Que recurso utilizou?

Controle de entrada e saída

Pacote java.io

Leitura/Escrita de Dados

Orientada a bytes (modo ‘binário’) Orientada a caracteres (modo ‘texto’) Serialização de Objetos

Outros

Acesso Aleatório: classe RandomAccessFile Informações sobre arquivos e diretórios: classe File

Uma stream de I/O gera o caminho por meio do qual seus programas podem enviar uma sequência de bytes de uma fonte até um destino. Uma stream de entrada é uma fonte (ou produtor) de bytes e uma stream de saída é o destino (ou consumidor).

Todas as funções de I/O stream tratam os arquivos de dados ou os itens de dados como uma corrente ou um fluxo (stream) de caracteres individuais. Se for escolhida uma função de stream apropriada, a aplicação poderá processar dados em qualquer tamanho ou formato, desde simples caracteres até estruturas de dados grandes e complicadas. Tecnicamente falando, quando um programa usa uma função stream para abrir um arquivo para I/O, o arquivo que foi aberto é associado com uma estrutura do tipo FILE que contém informações básicas sobre o arquivo.

c. getChar para leitura de um caractere, com um parâmetro do tipo String contendo um conjunto de caracteres aceitos.

5. Faça uma classe executável Java que teste entradas de dados para cada um dos métodos implementados no enunciado 4 e trate possíveis exceções (problemas de conversão com a estrutura try-catch).

5. Controle de entrada (I/O)

Exercício de nivelamento – I/O

Você já desenvolveu alguma aplicação que utilizou manipulou arquivos em disco? Em que linguagem? Trabalhou com gravação de objetos? Que recurso utilizou?

Controle de entrada e saída

Pacote java.io

Leitura/Escrita de Dados

Orientada a bytes (modo ‘binário’) Orientada a caracteres (modo ‘texto’) Serialização de Objetos

Outros

Acesso Aleatório: classe RandomAccessFile Informações sobre arquivos e diretórios: classe File

Uma stream de I/O gera o caminho por meio do qual seus programas podem enviar uma sequência de bytes de uma fonte até um destino. Uma stream de entrada é uma fonte (ou produtor) de bytes e uma stream de saída é o destino (ou consumidor).

Todas as funções de I/O stream tratam os arquivos de dados ou os itens de dados como uma corrente ou um fluxo (stream) de caracteres individuais. Se for escolhida uma função de stream apropriada, a aplicação poderá processar dados em qualquer tamanho ou formato, desde simples caracteres até estruturas de dados grandes e complicadas. Tecnicamente falando, quando um programa usa uma função stream para abrir um arquivo para I/O, o arquivo que foi aberto é associado com uma estrutura do tipo FILE que contém informações básicas sobre o arquivo.

Uma vez aberta a stream, é retornado um ponteiro para a estrutura FILE. Este ponteiro FILE – algumas vezes chamado de ponteiro stream ou stream – é usado para fazer referência ao arquivo para todas as entradas/saídas subsequentes.

Todas as funções de I/O stream fornecem entrada e saída bufferizada, formatada ou não formatada. Uma stream bufferizada proporciona uma localização de armazenamento intermediária para todas as informações que são provenientes de stream e toda saída que está sendo enviada a stream. I/O em disco é uma operação que toma tempo, mas a bufferização da stream agilizará sua aplicação. Ao invés de introduzir os dados stream, um caractere ou uma estrutura a cada vez, as funções I/O stream acessam os dados em um bloco de cada vez.

À medida que a aplicação necessita processar a entrada, ela simplesmente acessa o buffer, o que é um processo muito mais rápido. Quando o buffer estiver vazio, será acessado um novo bloco de disco. O inverso também é verdadeiro para saída stream. Ao invés de colocar fisicamente na saída todos os dados, à medida que é executada a instrução de saída, as funções de I/O stream colocam todos os dados de saída no buffer. Quando o buffer estiver cheio, os dados serão escritos no disco.

Dependendo da linguagem de alto nível que estiver sendo utilizada, pode ocorrer um problema de I/O bufferizado. Por exemplo, se o programa executar várias instruções de saída que não preencham o buffer de saída, condição necessária para que ele fosse descarregado no disco, aquelas informações serão perdidas quando terminar o processamento de programa.

A solução geralmente envolve a chamada de uma função apropriada para “limpar” o buffer. É claro que uma aplicação bem escrita não deverá ficar dependendo destes recursos automáticos, mas deverá sempre detalhar explicitamente cada ação que o programa deve tomar. Mais uma observação: se a aplicação terminar de maneira anormal quando se estiver usando stream I/O, os buffers de saída podem não ser esgotados (limpos), resultando em perda de dados.

O último tipo de entrada e saída é chamado “low-level I/O” – I/O de baixo nível. Nenhuma das funções de I/O de baixo nível executa bufferização e formatação. Ao invés disso, elas chamam diretamente os recursos de I/O do sistema operacional. Estas rotinas permitem acessar arquivos e dispositivos periféricos em um nível mais básico do que as funções stream.

Os arquivos abertos desta maneira retornam um manipulador de arquivo, um valor inteiro que é utilizado para fazer referência ao arquivo em operações subseqüentes. Em geral, é uma prática ruim de programação misturar funções de I/O stream com rotinas de baixo nível.

Como as funções stream são bufferizadas e as funções de baixo nível não, a tentativa de acessar o mesmo arquivo ou dispositivo por dois métodos diferentes leva à confusão e à eventual perda de dados nos buffers.

No documento Java Interfaces Gráficas e Banco de Dados (páginas 46-52)

Documentos relacionados