Departamento de Ciência da Computação
LP: Laboratório de Programação Apontamento 14
Prof. ISVega Maio de 2004
Mecanismo de Exceções em Java
CONTEÚDO
14.1 Erros, Faltas e Falhas . . . 1 14.2 Tratamento de Exceções em Java . . . 3 14.2.1Hierarquia de Exceções . . . 6 14.2.2Lançamento e Captura de Exceções . . . . 7 Exercícios . . . 12
Objetivos • Mostrar o mecanismo de exceções do ambiente Java.
14.1 Erros, Faltas e Falhas
Erros Erros introduzem faltas nos programas que, ao serem executadas, provocam falhas de execução. Erros podem e devem ser corrigidos.
Exemplo 14.1 Situações comuns de erros que geram faltas:
• Divisão por zero.
• Acesso a um arrayutilizando-se um índice inválido.
• Tentativa de usar uma referêncianull.
Exceções Uma exceção é um sinal indicando uma situação excepcional, provocada por um fator externo ao programa. A ocorrência deste problema deve ser tratada por um trecho de programa que varia em natureza e quantidade de software para software.
Exemplo 14.2 Situações comuns que geram exceções (Figura 14.1):
• Tentativa de abrir um arquivo inexistente. • Esgotamento de memória.
Figura 14.1: Situações de erro exigem tratamento.
¨ Exceções são problemas causados por uma fonte externa ao programa. Quando uma falha acontece devido a esta fonte externa, a instrução faltosa gera uma exceção (throw an exception). Estes eventos podem ocorrer a qualquer momento, e o seu efeito é o de interromper a execução, caso a aplicação não tenha sido preparada para tratá-los (Figura 14.2).
Figura 14.2: A execução de uma instrução faltora provoca a ocorrência de uma falha, gerando uma exceção.
Estratégias de Tratamento de Exceções Três grandes estratégias podem ser aplica-das para lidar com exceções:
3. Programar a lógica normal, separada do tratamento da exceção. O texto que trata a exceção está localizado na região onde a exceção pode ocorrer. A vanta-gem deste enfoque é a proximidade entre a região de ocorrência da exceção e a região onde ela é tratada.
Exemplo 14.3 A Figura 14.3-a mostra o mapa de execução de um modelo de apli-cação capaz de tratar exceções segundo esta última estratégia. Dois cenários de execução são apresentados:
• Figura 14.3-b: um cenário normal de execução. Neste caso, não ocorre falha
no ponto a.
• Figura 14.3-c: um cenário snormal de execução. Neste caso, ocorre falha no
ponto a, provocando um desvio para o trecho de rota que trata a falha.
a tratamento [ Exceção ] (a) a tratamento [ Exceção ] (b) a tratamento [ Exceção ] (c)
Figura 14.3: (a) Um mapa de execução com tratamento de exceção, (b) um cenário normal de execução, (c) e outro anormal.
¨
14.2 Tratamento de Exceções em Java
Blocos try Uma exceção que ocorre em um bloco try é normalmente tratada por um código especificado no bloco catch imediato:
hPadrão de tratamento de exceções em Javai≡
try {
// lógica "normal" (ignorando quaisquer exceções" }
catch( <Tipo da Exceção> exceção ) { // tratamento da exceção
Exemplo 14.4 Considere o mapa de execução de uma aplicação que solicita um número para o usuário, mostrado na Figura 14.4(a).
main()
dado ← obterString() numero ← converterInt( dado )
mostrar( numero ) exit( 0 )
(a)
main()
dado ← obterString() numero ← converterInt( dado )
mostrar( numero ) exit( 0 )
(b)
main()
dado ← obterString() numero ← converterInt( dado )
(c)
Figura 14.4: Um mapa de execução (a) para conversão de texto em número, um cenário normal (b) e outro anormal (c) de execução.
Supondo que o valor do dado de entrada corresponda a 2, este mapa é percorrido
do início ao fim sem a ocorrência de erros. Este cenário normal pode ser visualizado como na Figura 14.4(b). Entretanto, se2.5for usado como valor do dado de entrada,
um cenário anormal é observado pela ocorrência de uma exceção, como mostrado na Figura 14.4(c).
Este mapa pode ser implementado da seguinte forma em Java: hExemplo de um programa com faltai≡
import javax.swing.JOptionPane; public class Aplicacao {
public static void main( String[] args ) { String dado =
JOptionPane.showInputDialog( "Digite um numero:" ); int numero = Integer.parseInt( dado ); // <- falta System.out.println( numero );
System.exit( 0 ); }
}
A ocorrência da exceção é conseqüência de uma falha de execução. Tais exceções podem ser tratadas por programação Figura 14.5.
main()
dado ← obterString() numero ← converterInt( dado )
mostrar( numero ) exit( 0 )
[ Exceção ]
mostrar ( “Dado não numérico” )
Figura 14.5: Mapa que mostra o tratamento da exceção.
main()
dado obterString()
numero converterInt( dado )
mostrar( numero ) exit( 0 ) [ Exceção ]
mostrar ( “Dado não numérico” )
(a)
main()
dado obterString()
numero converterInt( dado )
mostrar( numero ) exit( 0 ) [ Exceção ]
mostrar ( “Dado não numérico” )
(b)
Figura 14.6: Um mapa de execução para conversão de texto em número, um cenário com tratamento da exceção (a) e outro normal (b) de execução.
Em Java, pode-se tratar a exceção provocada pela falha de execução por um bloco
try:
hExemplo de um programa com falta e tratamento de exceçãoi≡
import javax.swing.JOptionPane; public class Aplicacao {
public static void main( String[] args ) { String dado =
JOptionPane.showInputDialog( "Digite um numero:" ); int numero = -1;
try {
numero = Integer.parseInt( dado ); }
catch( NumberFormatException ref ) { JOptionPane.showMessageDialog( null,
"Voce deve digitar um numero", "Formato de numero invalido", JOptionPane.ERROR_MESSAGE ); } System.out.println( numero ); System.exit( 0 ); } } ¨
14.2.1 Hierarquia de Exceções
A tecnologia Java classifica os eventos gerados pelas falhas de execução em erros e exceções. Estas, por sua vez, podem ser exceções pré-definidas ou definidas pelo
usuário (Figura 14.7).
RuntimeException Usuário Error Exception
Throwable
Figura 14.7: Classificação de eventos gerados por falhas (dia-grama de classes UML).
• Throwable – unifica as noções de erros e exceções.
• Error - não deve ser tratado; deve ser corrigido.
• Exception – pode ser tratado.
– RuntimeException – recebem um tratamento padrão do ambiente de
exe-cução Java.
– Usuário – para tratamento especificado pelo usuário.
Dos diversos erros e exceções definidos pela tecnologia Java, as seguintes são as mais comuns:
• IOException – um problema de comunicação externa.
– FileNotFoundException – arquivo inexistente
– EOFException – tentativa de leitura após o término do arquivo
• NullPointerException – tentativa de usar um contexto null
(RuntimeException).
• NumberFormatException– tentativa converter um String não-numérico em
nú-mero (RuntimeException).
• OutOfMemoryError– programa que esgotou toda a memória disponível (Error).
• IllegalArgumentException – argumentos ilegais na execução de um método.
14.2.2 Lançamento e Captura de Exceções
Lançamento de Exceções O lançamento de uma exceção é feito quando se cria um objeto de uma classeThrowable, passando-a para o mecanismo throw.
Exceções podem ser lançadas apenas durante a execução de um método, desde que haja uma indicação de quais classes de exceções ele poderá lançar.
Exemplo 14.5 Considere o tanque representado pelo esquema da Figura 14.8.
co nt eú d o ca p ac id ad e d el ta Tanque
Em Java, o tanque pode ser descrito da seguinte forma: hlab/tanque/Tanquei≡
public class Tanque {
public int capacidade = 5000; // litros public int conteudo; // do tanque
hTanque: métodosi
}
O método de construção de tanques vazios é imediato: hTanque: métodosi≡
// Construtor de tanques vazios: public Tanque() {
conteudo = 0; }
Entretanto, pode-se construir um tanque a partir de uma determinada quantidade inicial de água. Neste caso, duas situações deverão ser tratadas no modelo compu-tacional do tanque:
• quantidade inicial contendo um valor negativo, a qual deverá ser rejeitada,
impedindo-se a construção do respectivo tanque.
• quantidade inicial superando a capacidade do tanque, que também deverá
ser rejeitada, impedindo-se a construção do respectivo tanque.
Para impedir que um objeto da classe Tanque seja criado, lança-se uma exceção
apropriada:
hTanque: métodosi+≡
public Tanque( int inicial )
throws TanqueTransbordouException, IllegalArgumentException { if( inicial < 0 ) {
throw new IllegalArgumentException(); }
int delta = inicial - capacidade; if( delta > 0 ) {
throw new TanqueTransbordouException( this, delta ); }
conteudo = inicial; }
Este construtor faz uso de duas classes de exceção:
• IllegalArgumentException– indicando que a quantidade inicial é ilegal. Esta
classe é oferecida pela bibliteca de classes do ambiente Java.
• TanqueTransbordouException – criada para este programa, indicando que o
tanque contém excesso de água. É um exemplo de exceção do usuário.
A codificação da classeTanqueTransbordouException segue o roteiro estabelecido
pela tecnologia Java:
hlab/tanque/TanqueTransbordouException.javai≡
public class TanqueTransbordouException extends Exception { public Tanque tanqueTransbordado;
public int excesso;
public TanqueTransbordouException( Tanque novo,
int quantidade ) { super(); tanqueTransbordado = novo; excesso = quantidade; } }
O método para inserir uma determinada quantidade de água no tanque pode ser
descrito da seguinte forma: hTanque: métodosi+≡
public void acrescentar( int quantidade )
throws TanqueTransbordouException, IllegalArgumentException { // 1: verificação de argumento
if ( quantidade < 0 ) {
throw new IllegalArgumentException(); }
// 2: verificação de transbordamento
int delta = ( quantidade + conteudo ) - capacidade; if ( delta > 0 ) {
throw new TanqueTransbordouException( this, delta ); }
// 3: confirmação de conteúdo conteudo += quantidade;
As duas primeiras verificações podem lançar exceções: uma devido a um valor nega-tivo, outra devido ao transbordamento do tanque de água. Caso nenhuma exceção seja lançada, o conteúdo do tanque é alterado de acordo com a quantidade de água informada.
A retirada de água segue um padrão similar, devendo-se considerar, no entanto, a possibilidade de retirada além do conteúdo atual do tanque:
hTanque: métodosi+≡
public void retirar( int quantidade )
throws TanqueInsuficienteException, IllegalArgumentException { // 1: verificação de argumento
if ( quantidade < 0) {
throw new IllegalArgumentException(); }
// 2: verificação de falta
int delta = quantidade - conteudo; if( delta > 0 ) {
throw new TanqueInsuficienteException( this, delta ); }
// 3: confirmação de conteúdo conteudo -= quantidade;
}
Observa-se a utilização de uma nova classe de exceção:
TanqueInsuficienteException.
Esta classe segue o formato padrão sugerido pela tecnologia Java: hlab/tanque/TanqueInsuficienteException.javai≡
public class TanqueInsuficienteException extends Exception { public Tanque tanqueInsuficiente;
public int falta;
public TanqueInsuficienteException( Tanque novo,
int quantidade ) { super(); tanqueInsuficiente = novo; falta = quantidade; } }
¨ Captura de Exceções As exceções lançadas durante a execução das instruções de um método podem ser capturadas pelo próprio programa, ou, em último caso, pelo ambiente de execução da tecnologia Java.
A captura de uma exceção lançada é feita com o uso do mecanismo try-catch. No
blocotry, inserem-se os métodos que, ao serem executados, podem lançar exceções.
Caso alguma for lançada, a sua captura se dará em algum catch indicado junto ao
mecanismo try.
Exemplo 14.6 No caso do tanque, o mecanismo de captura de exceções poderia ser utilizado da seguinte forma:
hlab/tanque/Cenario.javai≡
public class Controlador { public Tanque t1;
public void criarTanque() { t1 = new Tanque(); }
public void aumentar() { try {
System.out.println( "Conteudo = " + t1.conteudo ); t1.acrescentar( 4000 );
System.out.println( "Conteudo +4000 = " + t1.conteudo ); t1.acrescentar( 2000 ); // <- (*) } catch( IllegalArgumentException e ) { System.err.println("Quantidade negativa"); } catch( TanqueTransbordouException e ) { // <- (**) System.err.println( "Excesso de " + e.excesso ); }
} }
Depois de criado um objeto da classe Controlador, ao se enviar a mensagem
aumentar(), uma exceção será lançada quando o objeto t1 receber a
mensa-gem marcada com (*). A captura desta exceção é feita no catch marcado com
E
XERCÍCIOS
14.1
Escrever um programa que, ao ser executado, obtenha dois números do usuário (via teclado) e mostre a divisão entre eles.Tarefa 14.1.1 Crie o projeto ex14.1.
Tarefa 14.1.2 Crie a classe Divisor, contendo o método dividir(a:int,
b:int):int. Ao ser executado, este método divide o valor da variável a pelo
va-lor da variávelb, retornando o resultado.
Tarefa 14.1.3 Qual resultado é calculado quando os números de entrada são a=3
e b=6?
Tarefa 14.1.4 Qual exceção é gerada quanto se tenta calcular a divisão por ZERO (ou seja, b=0)? Como pode ser tratada?
14.2
No programa anterior, substitua os tipos das variáveis ae b pordouble erepita o experimento. Como se diferenciam os resultados?
14.3
PROBLEMA DE SCOTT Considere o seguinte problema, definido paraintei-ros positivos:
a) Escolha um número. b) Repetidamente, faça:
• Se o número for 1, páre.
• Se o número for par, divida-o pela metade.
• Se o número for ímpar, multiplique-o por 3 e some 1.
Ex.: começando pelo número 17, obtém-se a seqüência:
h17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1i
Este procedimento sempre pára qualquer entrada? Até agora, este é um problema sem solução: não se conseguiu provar que sempre pára, nem se conseguiu um contra-exemplo.
Tarefa 14.3.1 Escreva uma aplicação que faça o seguinte: a) Imprima seu nome.