[RESOLVIDO] Dúvida com exceptions

26 respostas
S

Boa tarde galera! Estou no capítulo 11 da apostila FJ11, e algumas dúvidas surgiram:

1. Exception é uma mensagem que o sistema retorna caso algo dê errado? Essa mensagem deve ser tratada (checked) ou não (unchecked)? Caso não seja tratada (unchecked) os métodos retornarão a excessão até onde não der mais (talvez no método main?) E encerrará o sistema todo ali?

2. Todos os métodos que eu criar devem lançar excessões caso algo de errado aconteça?

3. A criação de uma classe exception unchecked se deve pelo extends RuntimeException e a checked pelo extends Exception?

public class SaldoInsuficienteException extends RuntimeException {
	
	public SaldoInsuficienteException(String mensagem) {
		super(mensagem);
	}
}

Esse super é um método herdado da onde? Da classe exception?

4.

"Em sistemas de verdade, é muito comum que quem saiba tratar o erro é aquele que chamou o método e não a própria classe! Portanto, nada mais natural do que a classe sinalizar que um erro ocorreu."

Caso use uma exception checked, não teríamos a quebra de encapsulamento, já que o classe que irá usar o método deverá saber qual como tratar o erro de outra classe?

5. Como eu descubro todas as excessões que herdaram de RuntimeExceptions pra evitar de ficar criando classes de excessões?

26 Respostas

M

Amigo,

acho que você está confundindo algumas coisas, referente a Exception.

Excpetion, é uma classe que a JVM o o desenvolvedor gera quando ocorre algum error. E esta, é definida como checked, isto é, o programador deveras sempre tratar ela.

Uma excessao do tipo RuntimeException, não há necessidade de tratar, mesmo havendo na assinatura do método.

"Todos os métodos que eu criar devem lançar excessões caso algo de errado aconteça? "
R. Depende, a maioria dos casos sim, mas tem situações, que eu, particularmente, prefiro retornar um boolean ou mesmo um inteiro.

"Caso use uma exception checked, não teríamos a quebra de encapsulamento, já que o classe que irá usar o método deverá saber qual como tratar o erro de outra classe? "
R. Encapsulamento é outro departamento, referente a visibilidade de variáveis, métodos e classes.

ats,

S

"Todos os métodos que eu criar devem lançar excessões caso algo de errado aconteça? "
R. Depende, a maioria dos casos sim, mas tem situações, que eu, particularmente, prefiro retornar um boolean ou mesmo um inteiro.

E como vou saber quando lançar uma exceção? Qual exceção lançar? Onde tem a lista de exceções java?

"Caso use uma exception checked, não teríamos a quebra de encapsulamento, já que o classe que irá usar o método deverá saber qual como tratar o erro de outra classe? "
R. Encapsulamento é outro departamento, referente a visibilidade de variáveis, métodos e classes.

Mas eu preciso saber o funcionamento do método para tratar o erro? Se sim, aí há uma quebra de encapsulamento (pelo que entendi de encapsulamento).

M

Você irá lançar uma excessão, quando seu método gerar um error. Por exemplo, criaste uma função que conecta um servidor. Caso não consiga a conexão,
você irá gerar uma excessão. Outro exemplo, bem bobo, para serve; Criou uma função que soma dois valores, caso esta soma ultrapasse o valor 1000, irá gerar uma excessão.
Resumindo, irá gerar quando ocorrer erros na sua aplicação. E você pode gerar excessões personalizadas, extendendo a classe Exception.
Consegues a lista de excessões dos metodos, vendo a assintura do metodo.

O funcionamento do método, irás ver através da sua assintura. Por exemplo:
public int somar(int a,int b) thows Exception{`}

Este método eu sei que irá somar dois valores, e retornará um int. E também pode gerar uma excessão.
Mas quando irá gerar uma excessão ? Atráves da documentação do método, que poderás saber !!!
Ou criando uma excessão personalizada, utilizando o mesmo exemplo.

public int somar(int a,int b) thows UltrapassouLimite1000{`}
Com isso, sei que pode gerar uma excessao, quando a soma ultrapassar o limite de 1000. Mas caso fique com a dúvida, deves sempre verificar a documentação
do método.

ats,

drigo.angelo

1- Quando você souber que alguma coisa pode dar errado, por exemplo se voce depende que o nome, vindo do formulário não seja nulo, você pode lançar uma excessão caso seja nulo :smiley:

2- Lance a excessão que represente melhor o erro que você previu

3- Tem uma lista das exceções do Java na documentação da API, aliás é sempre bom ter ela sempre por perto

Não, não haverá quebra do encapsulamento justamente porque voce não sabe como a excessão é lançada, você só sabe que algo pode dar errado, por exemplo, quando você vai fazer uma consulta a um bd, caso algo dê errado provavelmente será lançada uma SQLException, o objeto que chamou a classe que trata da comunicação com o banco de dados não sabe como a comunicação é feita, apenas sabe que algo pode dar errado e como proceder se algo der errado :stuck_out_tongue:

[]'s

S

Vamos ver se está correto meu entendimento:

Quando deve se lançar uma exceção?

Quando eu souber que uma coisa pode dar errado e eu quero interromper aquele fluxo, finalizar ou tratá-lo. Geralmente usa-se em métodos críticos? Ex: sacar(conta c). Não vou lançar uma exceção em um método getter por ex?

Checked exceptions são filhas da classe Exception e quando um método lança esse tipo de exceção, a pessoa que invocou o método deve TRATAR (try-catch) ou RELANÇÁ-LA (throws).
Usa-se quando existe a chance de recuperar-se do erro?
Caso relance, e ninguém trate o que acontece? Encerra a aplicação?

Unchecked exceptions são fihas da classe RuntimeException e não precisam ser tratadas ou relançadas, porém, podem ser tratadas ou relançadas.
Usa-se quando não existe a chance de recuperar-se do erro?
Caso seja lançada a exceção (ocorreu o erro) e ninguém trate a exceção, o que acontece? Encerra a aplicação?

Mais dúvidas…

[]´s

Alfredo_Barbosa

“E como vou saber quando lançar uma exceção? Qual exceção lançar? Onde tem a lista de exceções java?”

Stark, as exceções todas derivam da classe Exception e eu ouvi dizer que nenhuma tem implementação
ou seja, você só usa um nome específico pra uma exceção pra facilitar a leitura do seu código ou pra tratar erros diferentes

por exemplo

try {
    //o bloco pode lançar uma exceção pela entrada de dados, outra pelo tipo e outra pela divisão por zero
} catch(EntradaException ex) {
    //aqui você resolve considerando que houve um problema na entrada de dados
} catch(ConversãoDaEntradaException ex) {
    //aqui você resolve a conversão, porque o usuário entrou uma string que não pode ser convertida pra um número
} catch(ArithmeticException ex) {
    //aqui você decide o que faz se houver uma divisão por zero
}

isso porque se só houvesse a classe Exception você só poderia fazer um tratamento genérico pra todos os problemas

S

Concordo. E sobre as minhas conclusões, estão corretas?

[]´s

Alfredo_Barbosa

stark:
Quando deve se lançar uma exceção?

Quando eu souber que uma coisa pode dar errado e eu quero interromper aquele fluxo, finalizar ou tratá-lo. Geralmente usa-se em métodos críticos? Ex: sacar(conta c). Não vou lançar uma exceção em um método getter por ex?


Quando você souber que algo pode dar errado, sim. Faz-se o tratamento de exceções sempre que algo pode dar errado e você quer corrigir o problema. Ex: esperando um número do usuário e ele pode digitar letras, pedindo pro programa abrir um arquivo e ele pode não estar lá, tentando dividir por uma variável e ela pode assumir o valor zero…

stark:
Checked exceptions são filhas da classe Exception e quando um método lança esse tipo de exceção, a pessoa que invocou o método deve TRATAR (try-catch) ou RELANÇÁ-LA (throws).
Usa-se quando existe a chance de recuperar-se do erro?
Caso relance, e ninguém trate o que acontece? Encerra a aplicação?

Sim, essas exceções devem ser tratadas de alguma forma.
Esse tipo de exceção gera um erro fatal, que, se não for bem tratado, não tem como o programa seguir com a execução.
Não existe a possibilidade de ninguém o tratar, você não vai conseguir compilar um código assim.

stark:
Unchecked exceptions são fihas da classe RuntimeException e não precisam ser tratadas ou relançadas, porém, podem ser tratadas ou relançadas.
Usa-se quando não existe a chance de recuperar-se do erro?
Caso seja lançada a exceção (ocorreu o erro) e ninguém trate a exceção, o que acontece? Encerra a aplicação?

Existe a chance de contornar o erro. Caso ninguém trate a exceção, é possível que o programa se encerre ou até que na execução você nem saiba que ocorreu um erro…

Alfredo_Barbosa

tem mais um detalhe… pelo que EU saiba, a gente está falando de exceções OBRIGATÓRIAS E OPCIONAIS, não de checked e unchecked, porque existem exceções reconhecidas pelo java (checked) que você pode tratar ou não (opcionais), como o caso da conversão de string pra um tipo numérico. O java lança uma exceção sem você mandar fazer isso, mas se você trata ou não é problema seu. Alguém mais letrado pode dizer se estou certo ou não?

Alfredo_Barbosa

tem ainda a classe Error - esse sim não tem volta…
nem como tratar, se der isso o programa para.
repare que um RuntimeException pode ou não ser tratado
um Exception DEVE ser tratado
e um Error não tem como tratar… ^^

ViniGodoy

Um exemplo de Error comum é o OutOfMemoryError, indicando que acabou a memória disponível para usa aplicação rodar.

Quando isso acontece, a thread onde esse falha ocorreu morre imediatamente, e o erro é disparado depois que isso ocorre. Ou seja, já não tem mais volta. Outro clássico é o StackOverflowError, que ocorre quando vc chamou um método A, que chamou um B, que chamou novamente A. Isso gera tantas chamadas, que a pilha que controla quem chamou quem fica sem memória e estoura o erro.

Um bom artigo que explica essas diferenças é esse aqui: http://blog.caelum.com.br/lidando-com-exceptions/

S
Alfredo Barbosa:
tem ainda a classe Error - esse sim não tem volta... nem como tratar, se der isso o programa para. repare que um RuntimeException pode ou não ser tratado um Exception DEVE ser tratado e um Error não tem como tratar... ^^

Agora eu entendi Alfredo.

Vini: Eu li esse artigo diversas vezes e vi que até a API do java as vezes obriga a tratar a exceção mesmo ela não sendo tratável (SQLException).
Tentei dar um throw Exception em uma função e o Eclipse pediu pra que eu tratasse o erro ou passasse adiante.
Já um throw RuntimeException (e suas filhas) ele não pede...

Entendi que deve-se usar:

Checked exceptions quando o erro é tratável e você quer passar isso para quem chamou o método.
Unchecked exceptions quando o erro não é tratável e você quer encerrar o programa ali. Pode ser tratado, mas não é aconselhável já que é um erro de programação que gera instabilidade.

[color=red]Correto pessoal? Sim ou não?[/color]

Dúvidas remanescentes:

1.

Existe a chance de contornar o erro. Caso ninguém trate a exceção, é possível que o programa se encerre ou até que na execução você nem saiba que ocorreu um erro...

Quer dizer que se o programa lançar uma exceção e essa não for tratada, corre o risco do programa continuar executando instavelmente? Então não adianta passar exceção!

2.
public class ValorInvalidoException extends RuntimeException{
	
	public ValorInvalidoException(String mensagem) {
		super(mensagem);
	}
}

O que vem a ser esse método super?

Obrigado pela ajuda de todos. Agora começo a entender o conceito (sem conceito não da pra continuar né?)

[]´s

ViniGodoy

A exception mata apenas a thread que a disparou. Então, outras partes do programa podem continuar rodando sim.

Para evitar isso, você pode registrar um DefaultUncaughtExceptionHandler, no caso de aplicações desktop. No caso de aplicações web, a maior parte dos servidores de aplicação tem uma forma de tratar o que não foi capturado.

O DefaultUncaughtExceptionHandler é o que o java chama quando a exceção não é capturada. Por padrão, ele só imprime o StackTrace no System.err. Eu geralmente sobrescrevo o handler para logar a exceção em arquivo e também finalizar a aplicação com um System.exit(1)

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable ex) { salvarEmArquivo(ex, t); System.exit(1); } });

ViniGodoy

Super chama um método da superclasse. No caso do construtor, o super sozinho chama o construtor da superclasse.

S

ViniGodoy:
A exception mata apenas a thread que a disparou. Então, outras partes do programa podem continuar rodando sim.

Para evitar isso, você pode registrar um DefaultUncaughtExceptionHandler, no caso de aplicações desktop. No caso de aplicações web, a maior parte dos servidores de aplicação tem uma forma de tratar o que não foi capturado.

O DefaultUncaughtExceptionHandler é o que o java chama quando a exceção não é capturada. Por padrão, ele só imprime o StackTrace no System.err. Eu geralmente sobrescrevo o handler para logar a exceção em arquivo e também finalizar a aplicação com um System.exit(1)

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable ex) { salvarEmArquivo(ex, t); System.exit(1); } });

Entendi! Acredito que quando entrar no capítulo de threads eu vou entender ainda mais.
Que legal, você re-escreveu o método pra quando acontecer a exceção, logar num arquivo e depois encerrar o programa. Pelo jeito essa é uma parte avançada né? Ta na onde isso? Fj21 ou em algum livro de design patterns?

No meu atual estágio de conhecimento, poderia fazer isso no try-catch?

[]´s

drigo.angelo
stark:
Dúvidas remanescentes: 1.
Existe a chance de contornar o erro. Caso ninguém trate a exceção, é possível que o programa se encerre ou até que na execução você nem saiba que ocorreu um erro...
Quer dizer que se o programa lançar uma exceção e essa não for tratada, corre o risco do programa continuar executando instavelmente? Então não adianta passar exceção!
A excessão vai subindo na pilha de chamadas até ser tratada, se passar do método main e ninguém a tratar, acho que o programa é encerrado. Mas não é raro você ver em alguma parte do código de alguém sem noção algo do tipo:
try{ ...
}catch(Exception e){} //Isso mesmo, não faz nada !!!!!!!!!!
Isso pode fazer com que o programa continue a execução de forma instável já que ocorreu um erro e este não foi tratado corretamente!
2.
public class ValorInvalidoException extends RuntimeException{
	
	public ValorInvalidoException(String mensagem) {
		super(mensagem);
	}
}
O que vem a ser esse método super?
super( ... ) chama o construtor da superclasse :D

this( ... ) chama outro construtor da sua classe

eu acho que isso só pode ser feito dentro de um construtor.
para chamar um método da superclasse voce pode usar super.nomeDoMetodo( ... );

Update: Nem vi os ultimos posts xD;

[]'s

S

A excessão vai subindo na pilha de chamadas até ser tratada, se passar do método main e ninguém a tratar, acho que o programa é encerrado.
Mas não é raro você ver em alguma parte do código de alguém sem noção algo do tipo:
view plaincopy to clipboardprint?

try{ ... }catch(Exception e){} //Isso mesmo, não faz nada !!!!!!!!!!

Isso pode fazer com que o programa continue a execução de forma instável já que ocorreu um erro e este não foi tratado corretamente!

Certo. Mas se o cara não fizer esse tratamento de erro sem noção, vai encerrar a thread ou o main?

[]´s

drigo.angelo

Acho que encerra so a thread que deu erro mesmo

ViniGodoy

Não sei se esse assunto é coberto em uma das apostilas da Caelum. Eu nunca estudei por elas, só as li por cima para saber se indicaria ou não.

Esse é o diagrama do que acontece com uma exception quando ela não é capturada:

Em todos os casos, a thread é encerrada.

ViniGodoy

stark:
A excessão vai subindo na pilha de chamadas até ser tratada, se passar do método main e ninguém a tratar, acho que o programa é encerrado.
Mas não é raro você ver em alguma parte do código de alguém sem noção algo do tipo:
view plaincopy to clipboardprint?

try{ ... }catch(Exception e){} //Isso mesmo, não faz nada !!!!!!!!!!

Isso pode fazer com que o programa continue a execução de forma instável já que ocorreu um erro e este não foi tratado corretamente!

Certo. Mas se o cara não fizer esse tratamento de erro sem noção, vai encerrar a thread ou o main?

[]´s

O programa ignora o erro e toca a bola para frente, sem logar nada. Por isso é um tratamento “sem noção”.

S

ViniGodoy:
stark:
A excessão vai subindo na pilha de chamadas até ser tratada, se passar do método main e ninguém a tratar, acho que o programa é encerrado.
Mas não é raro você ver em alguma parte do código de alguém sem noção algo do tipo:
view plaincopy to clipboardprint?

try{ ... }catch(Exception e){} //Isso mesmo, não faz nada !!!!!!!!!!

Isso pode fazer com que o programa continue a execução de forma instável já que ocorreu um erro e este não foi tratado corretamente!

Certo. Mas se o cara não fizer esse tratamento de erro sem noção, vai encerrar a thread ou o main?

[]´s

O programa ignora o erro e toca a bola para frente, sem logar nada. Por isso é um tratamento “sem noção”.

}catch(Exception e){}: Sem noção pq ele captura a exceção e não faz nada, aí continua executando instavelmente.

Mas se ele [color=red]não [/color]tratar com try-catch, a thread se encerra por ali?

[]´s

ViniGodoy

stark:
}catch(Exception e){}: Sem noção pq ele captura a exceção e não faz nada, aí continua executando instavelmente.

Mas se ele [color=red]não [/color]tratar com try-catch, a thread se encerra por ali?

[]´s

Não. Ela vai para o método que chamou quem disparou a exception. Se ele não tratar, ela vai para o método que chamou o método, que disparou a exception. E se ninguém tratar, ela vai subindo, subindo, subindo até uma hora que chega no main, ou no run().

Se sair do método onde a thread começou, ela segue o ciclo do diagrama que postei, e então é encerrada.

Alfredo_Barbosa

você passa a exceção quando deseja tratá-la num escopo superior
tipo, tem um método A que chama um método B que lança uma exceção
você pode tratá-la no método B mesmo ou jogar pra fora
daí você vai ter que tratar no método A (se ela for obrigatória, senão você pode deixar passar…)

Checked exceptions quando o erro é tratável e você quer passar isso para quem chamou o método.
Unchecked exceptions quando o erro não é tratável e você quer encerrar o programa ali.

Na verdade ambos são tratáveis: ambos podem ser tratados ou lançados
a diferença entre eles é que o tratamento de um unchecked exception é opcional
enquanto o tratamento (ou lançamento para posterior tratamento) é obrigatório
se você não trata de alguma forma uma checked exception o programa não compila

ambas podem ser tratadas, há quem prefira tratar tudo que é exceção possível, há quem trate apenas as obrigatórias (e verifique as opcionais de outra forma)
uma unchecked exception é resultado de um erro de programação ou sacanagem do usuário
(você pede pra ele digitar um número e ele entra com um texto)
uma checked exception é um erro que aconteceu fora do escopo do programa
(o usuário apagou um arquivo e o programa não consegue encontrá-lo por exemplo)

S

ViniGodoy:
stark:
}catch(Exception e){}: Sem noção pq ele captura a exceção e não faz nada, aí continua executando instavelmente.

Mas se ele [color=red]não [/color]tratar com try-catch, a thread se encerra por ali?

[]´s

Não. Ela vai para o método que chamou quem disparou a exception. Se ele não tratar, ela vai para o método que chamou o método, que disparou a exception. E se ninguém tratar, ela vai subindo, subindo, subindo até uma hora que chega no main, ou no run().

Se sair do método onde a thread começou, ela segue o ciclo do diagrama que postei, e então é encerrada.

Vini: A primeira parte está perfeita, entendi.
Vou continuar estudando e tentar entender sobre thread, aí sim eu volto depois pra entender a segunda!

Muito obrigado pela ajuda, vou renomear o tópico como [RESOLVIDO]. Temos material suficiente aqui pra entender boa parte de exception.

S

você passa a exceção quando deseja tratá-la num escopo superior
tipo, tem um método A que chama um método B que lança uma exceção
você pode tratá-la no método B mesmo ou jogar pra fora
daí você vai ter que tratar no método A (se ela for obrigatória, senão você pode deixar passar…)

Checked exceptions quando o erro é tratável e você quer passar isso para quem chamou o método.
Unchecked exceptions quando o erro não é tratável e você quer encerrar o programa ali.

Na verdade ambos são tratáveis: ambos podem ser tratados ou lançados
a diferença entre eles é que o tratamento de um unchecked exception é opcional
enquanto o tratamento (ou lançamento para posterior tratamento) é obrigatório
se você não trata de alguma forma uma checked exception o programa não compila

ambas podem ser tratadas, há quem prefira tratar tudo que é exceção possível, há quem trate apenas as obrigatórias (e verifique as opcionais de outra forma)
uma unchecked exception é resultado de um erro de programação ou sacanagem do usuário
(você pede pra ele digitar um número e ele entra com um texto)
uma checked exception é um erro que aconteceu fora do escopo do programa
(o usuário apagou um arquivo e o programa não consegue encontrá-lo por exemplo)

Alfredo Barbosa: Agora sim estou com as dúvidas esclarecidas! Só falta entender aquela parte de thread, mas já é assuntou pra outro tópico.

Obrigado pela ajuda de todos.

[]´s

T

Tenho esse try, queria saber como que faço pra tratar um eventual erro, usando a Exception, mas quando houver esse erro o cursor voltar para codAlunofield(jtextField) pra o usuario digite novamente!! Alguem pode me ajudar???

try {

queryAluno = entityManager.createNamedQuery(Aluno.findByCodaluno);

queryAluno.setParameter(codaluno, Integer.parseInt(codAlunofield.getText()));

listAluno = queryAluno.getResultList();

nomeAlunoField.setText(listAluno.get(0).getNome());

cpfAlunoField.setText(listAluno.get(0).getCpf());

} catch ( Exception e) {

JOptionPane.showMessageDialog(null, Ocorreu um erro, use apenas numeros!);

e.printStackTrace();

codAlunofield.requestFocus();
}
Criado 22 de fevereiro de 2011
Ultima resposta 8 de nov. de 2012
Respostas 26
Participantes 6