Mecanismo de Exceções em Java - PUC-SP

Propaganda
Pontifícia Universidade Católica de São Paulo
Departamento de Ciência da Computação
Apontamento 14
Maio de 2004
LP: Laboratório de Programação
Prof. ISVega
Mecanismo de Exceções em Java
CONTEÚDO
14.1 Erros, Faltas e Falhas . . . . . . . . . . . .
14.2 Tratamento de Exceções em Java . . . . .
14.2.1Hierarquia de Exceções . . . . . . .
14.2.2Lançamento e Captura de Exceções
Exercícios . . . . . . . . . . . . . . . . . . . . . .
Objetivos
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
3
6
7
12
• 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 array utilizando-se um índice inválido.
• Tentativa de usar uma referência null.
¨
1
Laboratório de Programação
Maio de 2004
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
das para lidar com exceções:
Três grandes estratégias podem ser aplica-
1. Ignorar todas, considerando apenas as mais importantes. O código fica mais
claro, mas o programa irá se comportar de forma incorreta diante de uma situação inesperada.
2. Tratar cada possibilidade juntamente com a lógica principal. O código fica obscuro, mas o seu funcionamento é melhor. Nem todas as situções são previstas.
c
Copyright °1998-2004,
Dr. Italo S. Vega
14-2
Laboratório de Programação
Maio de 2004
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 vantagem 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 aplicaçã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.
[ Exceção ]
tratamento
(a)
a [ Exceção ]
tratamento
a [ Exceção ]
a
tratamento
(b)
(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
}
c
Copyright °1998-2004,
Dr. Italo S. Vega
14-3
Laboratório de Programação
Maio de 2004
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()
main()
main()
dado ← obterString()
dado ← obterString()
dado ← obterString()
numero ← converterInt( dado )
numero ← converterInt( dado )
numero ← converterInt( dado )
mostrar( numero )
mostrar( numero )
exit( 0 )
exit( 0 )
(a)
(b)
(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, se 2.5 for 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.
c
Copyright °1998-2004,
Dr. Italo S. Vega
14-4
Laboratório de Programação
Maio de 2004
main()
dado ← obterString()
[ Exceção ]
mostrar
( “Dado não numérico” )
numero ← converterInt( dado )
mostrar( numero )
exit( 0 )
Figura 14.5: Mapa que mostra o tratamento da exceção.
main()
main()
dado
[ Exceção ]
mostrar
( “Dado não numérico” )
numero
obterString()
converterInt( dado )
mostrar( numero )
exit( 0 )
(a)
dado
[ Exceção ]
mostrar
( “Dado não numérico” )
numero
obterString()
converterInt( dado )
mostrar( numero )
exit( 0 )
(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.
c
Copyright °1998-2004,
Dr. Italo S. Vega
14-5
Laboratório de Programação
Maio de 2004
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).
Throwable
Error
RuntimeException
Exception
Usuário
Figura 14.7: Classificação de eventos gerados por falhas (diagrama de classes UML).
c
Copyright °1998-2004,
Dr. Italo S. Vega
14-6
Laboratório de Programação
Maio de 2004
• 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 execuçã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
(RuntimeException).
–
tentativa
de
usar
um
contexto
null
• 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 classe Throwable, 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.
conteúdo
capacidade
delta
Exemplo 14.5 Considere o tanque representado pelo esquema da Figura 14.8.
Tanque
Figura 14.8: Esquema de um tanque de água.
c
Copyright °1998-2004,
Dr. Italo S. Vega
14-7
Laboratório de Programação
Maio de 2004
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 computacional 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;
}
c
Copyright °1998-2004,
Dr. Italo S. Vega
14-8
Laboratório de Programação
Maio de 2004
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 classe TanqueTransbordouException 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;
}
c
Copyright °1998-2004,
Dr. Italo S. Vega
14-9
Laboratório de Programação
Maio de 2004
As duas primeiras verificações podem lançar exceções: uma devido a um valor negativo, 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
TanqueInsuficienteException.
uma
nova
classe
de
exceção:
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;
}
}
c
Copyright °1998-2004,
Dr. Italo S. Vega
14-10
Laboratório de Programação
Maio de 2004
¨
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
bloco try, 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 mensagem marcada com (*). A captura desta exceção é feita no catch marcado com
TanqueTransbordouException, na linha (**).
¨
c
Copyright °1998-2004,
Dr. Italo S. Vega
14-11
Laboratório de Programação
Maio de 2004
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 valor da variável b, retornando o resultado.
Tarefa 14.1.3
e b=6?
Qual resultado é calculado quando os números de entrada são a=3
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 a e b por double e
repita o experimento. Como se diferenciam os resultados?
14.3 P ROBLEMA
DE
S COTT
Considere o seguinte problema, definido para intei-
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.
b) Para cada número de 1 até 20, imprima a linha que começa com o número,
seguido por dois pontos, seguido pela seqüência de Scott que começa com o
número. Separe os números da seqüência por um espaço. Ex.: no caso do
número 17:
17: 52 26 13 40 20 10 5 16 8 4 2 1
c
Copyright °1998-2004,
Dr. Italo S. Vega
14-12
Download