NÃO TRATAM ERROS
ESQUECEM DE TRATAR ERROS
DEIXAM O TRATAMENTO DE ERROS PARA "DEPOIS", QUE ACABA SENDO "NUNCA"
UM OBJETO DESCOBRE UM ERRO INTERNO
VALORES INCONSISTENTES DE VARIÁVEIS
ERROS COM OS OBJETOS OU DADOS QUE SÃO MANIPULADOS
UM ARQUIVO OU ENDEREÇO DE REDE INEXISTENTE
E MAIS CENTENAS DE EXEMPLOS DIFERENTES
O CÓDIGO DEVE REFLETIR O PROBLEMA A SER RESOLVIDO E NÃO AS CONDIÇÕES DE ERRO
O MECANISMO DE EXCEÇÃO DE JAVA PERMITE TRATAR ERROS E NÃO DEIXAR O CÓDIGO ILEGÍVEL
EXCEÇÕES PERMITEM TRATAR ERROS SEM INTRODUZIR FLAGS ESPECIAIS, VERIFICAR VALORES ESPECIAIS DE RETORNO, ETC.
ISSO PERMITE QUE O COMPILADOR FORCE O PROGRAMADOR A TRATAR OS ERROS
OS MÉTODOS INTERVENIENTES QUE NÃO CAPTURAM O ERRO NÃO PRECISAM TER CÓDIGO ESPECIAL PARA REPASSAR O ERRO PARA CIMA
É COMO SE O MECANISMO DE ERRO TIVESSE UM OUTRO "CANAL DE COMUNICAÇÃO" ENTRE MÉTODOS (ALÉM DO VALOR NORMAL DE RETORNO)
EXCEÇÕES SÃO OBJETOS
TODOS OS TIPOS DE EXCEÇÃO SÃO EXTENSÕES DA CLASSE Throwable
POR CONVENÇÃO, SUAS NOVAS EXCEÇÕES SERÃO SUBCLASSES DE Exception
Exception E SUAS SUBCLASSES SÃO EXCEÇõES VERIFICADAS
O COMPILADOR EXIGE QUE SEUS MÉTODOS LANCEM APENAS EXCEÇÕES QUE DEFINIRAM COM throws
AS CLASSES RuntimeException E Error E SUAS SUBCLASSES OCORREM COM MUITA FREQUÊNCIA E NÃO PRECISAM SER DECLARADAS
SÃO EXCEÇõES NÃO VERIFICADAS
VOCÊ VAI CRIAR SUAS PRÓPRIAS EXCEÇÕES EM DUAS SITUAÇÕES:
VOCÊ QUER ADICIONAR UM VALOR AO STRING QUE A EXCEÇÃO NORMAL MANTÉM
EXEMPLO: O OBJETO DE BAIXO NÍVEL QUE CAUSOU A EXCEÇÃO, DE FORMA QUE O CÓDIGO QUE TRATA A EXCEÇÃO POSSA ACESSAR O DANADO!
VOCÊ QUER CAPTURAR UM TIPO ESPECÍFICO DE EXCEÇÃO SEM SE PREOCUPAR COM OUTRAS EXCEÇÕES
UM EXEMPLO: ACRESCENTAMOS UM MÉTODO substituiValor À INTERFACE ComAtributos
SE O NOME DO ATRIBUTO A SUBSTITUIR NÃO EXISTE, TEMOS UM PROBLEMA QUE QUEREMOS TRATAR
VAMOS CRIAR UM NOVO TIPO DE EXCEÇÃO PARA REPRESENTAR O FATO
public class ExcecaoAtributoInexistente extends Exception { public String nomeAtributo; // os dados que geraram o erro ExcecaoAtributoInexistente( String nome ) { super( "Nao tem atributo chamado \"" + nome + "\"" ); nomeAtributo = nome; } }
USADO PARA LANÇAR EXCEÇÕES
public void substituiValor( String nome, Object novoValor ) throws ExcecaoAtributoInexistente { Atributo atrib = localiza( nome ); // procura o atributo if( atrib == null ) { // se não for localizado throw new ExcecaoAtributoInexistente( nome ); } atrib.setValor( novoValor ); }
TAMBÉM PODE LANÇAR UMA EXCEÇÃO ATRAVÉS DE UMA CHAMADA A UM MÉTODO QUE A LANCE
PARA DECLARAR QUE TIPOS DE EXCEÇÕES SÃO LANÇADAS POR UM MÉTODO
JAVA EXIGE ISSO PORQUE O TRATAMENTO DE ERRO É TÃO IMPORTANTE QUANTO O TRATAMENTO DOS CASOS NORMAIS
VOCÊ DECLARA PARÂMETROS, NÃO?
VOCÊ DECLARA O TIPO DE VALOR DE RETORNO, NÃO?
FAZ PARTE DO CONTRATO DO MÉTODO
APENAS EXCEÇÕES VERIFICADAS PRECISAM SER DECLARADAS
VOCÊ PODE LANÇAR EXCEÇÕES DE SUBCLASSES DAS CLASSES DE EXCEÇÃO DECLARADAS (DEVIDO AO POLIMORFISMO)
NÃO É UMA BOA IDÉIA PORQUE ESCONDE COISAS IMPORTANTES DO PROGRAMADOR
SE VOCÊ CHAMAR UM MÉTODO QUE PODE LANÇAR UMA EXCEÇÃO, VOCÊ PODE:
CAPTURAR A EXCEÇÃO DE TRATA-LA
CAPTURAR A EXCEÇÃO E LANÇAR OUTRA (MAPEAMENTO DE EXCEÇÃO) QUE VOCÊ DECLAROU COM throws
DECLARAR A EXCEÇÃO COM throws E DEIXA-LA PASSAR "PARA CIMA"
MAS AQUI VOCÊ PODE TAMBÉM ACIONAR UMA CLÁUSULA finally
A SINTAXE DO BLOCO try QUE CAPTURA EXCEÇÕES
try { comandos } catch( TipoDeExceção1 identificador1 ) { comandos } catch( TipoDeExceção2 identificador2 ) { comandos ... } finally { comandos }
O BLOCO try É EXECUTADO ATÉ QUE TERMINE NORMALMENTE OU QUE HAJA UMA EXCEÇÃO "EM BAIXO"
AO SUBIR, A EXCEÇÃO CHEGA NO BLOCO try E CADA catch É TESTADO ATÉ ENCONTRAR AQUELE (ÚNICO) QUE SE APLICA
ESTE BLOCO catch É EXECUTADO COM O IDENTIFICAR APONTANDO PARA O OBJETO DE EXCEÇÃO
O BLOCO finally SEMPRE É EXECUTADO QUANDO O try TERMINA
MESMO QUE HAJA break, return, ETC.
EXEMPLO NO USO DE substituiValor
Object valor = new Integer(1999); // Explique por que não usa int try { carroComAtributos.substituiValor( "DataFabricação", valor ); } catch( ExcecaoAtributoInexistente e ) { // Nao deveria ocorrer, mas recupera caso ocorra Atributo atrib = new Atributo( e.nomeAtributo, valor ); carroComAtributos.adiciona( atrib ); }
EXEMPLO: ROTINA QUE PROCURA UMA PALAVRA NUM ARQUIVO MAS QUE TEM QUE FECHAR O ARQUIVO EM TODAS AS CONDIÇÕES DE SAÍDA DA ROTINA (DEVIDO A EXCEÇÃO OU NÃO)
public boolean procuraPor( String arquivo, String palavra ) throws IOException { BufferedReader input = null; try { input = new BufferedReader( new InputStreamReader( new FileInputStream( arquivo ) ) ); StreamTokenizer st = new StreamTokenizer( input ); while( st.nextToken() != StreamTokenizer.TT_EOF ) { if( palavra.equals( st.toString() ) ) { return true; } } return false; } finally { if( input != null ) { input.close(); } } }
PARA CONDIÇÕES NÃO ESPERADAS
EXEMPLO: ATINGIR O FIM DE UMA ENTRADA É ESPERADO: NÃO USE EXCEÇÃO PARA CONTROLAR ISSO
QUAL IMPLEMEMTAÇÃO ABAIXO VOCÊ PREFERE?
while( (token = stream.next()) != Stream.END ) { processa( token ); } stream.close();
try { for(;;) { processa( stream.next() ); } } catch( StreamEndException e ) { stream.close(); }