Olá, gostaria de saber pq quando declaro throws estou tratando uma exception. Já não havia o try/catch na classe TestaConta tratando? Entendi que declarando throws diz que pode haver uma exception.
Olá, gostaria de saber pq quando declaro throws estou tratando uma exception. Já não havia o try/catch na classe TestaConta tratando? Entendi que declarando throws diz que pode haver uma exception.
Olá Kelvin. Basicamente a diferença entre o throws e o try/catch é:
throws: se ocorrer uma exceção, ela é capturada mas não tratada, ela é lançada para o método que a chamou. Exemplo: eu tenho a classe A e a classe B
class A{
B b = new B();
b.metodoException();
}
class B{
public void metodoException() throws Exception{
// se ocorrer alguma exceção aqui ela sera lançada para a classe A que foi que de onde o método foi chamado
}
}
try/catch: se ocorrer uma exceção, ela é capturada no try e tratada no catch.
Exemplo:
class A{
B b = new B();
b.metodoException();
}
class B{
public void metodoException() {
try{
// se ocorrer alguma exceção ela sera capturada aqui
}catch(Exception e){
// e tratada aqui sem que A nem saiba de qualquer problema
}
}
}
Já no caso de ter um método com com as duas declarações seria pelo fato de que pode ocorrer vários tipos de exceção num mesmo bloco.
Exemplo: eu posso ter um try/catch para tratar um divisão por zero
public void divisaoException(tipo valor1, tipo valor2) {
try{
// suponha que um dos valores seja nulo
valor1/valor2;
}catch(ExceptionDivisao ed){ Exceção da divisão por zero}
}
nesse caso vai ocorrer uma exceção não de divisão, mas de valor nulo, que não foi tratado, nesse caso você teria duas opções adicionar o throws pra tratar o valor nulo(que acho ter sido sua dúvida) ou o que considero mais adequado que é adicionar um segundo catch e nele tratar o valor nulo.
Oi Kelvin e João
Na linguagem java o comando para tratar a exceção é o try/catch
. O throws
na verdade não faz nenhum tratamento de erros, ele é apenas utilizado para demarcar que um método lança uma exceção que precisa ser tratada.
No java existem dois tipos de exceção: checked e unchecked (também conhecida como runtime exception).
Checked exceptions são as exceções que são filhas de Exception
mas não fazem parte da hierarquia de RuntimeException
. Essas exceções são geralmente utilizadas para indicar uma situação de erro esperada na regra de negócio, por exemplo, quando um usuário tenta sacar dinheiro de um caixa eletrônico ele pode não ter saldo suficiente ou a conta pode estar bloqueada, nesse caso, estamos executando uma operação ilegal no programa (um erro que seria indicado por uma exceção), mas essa exceção é esperada, já que ela faz parte do fluxo de negócio e, por isso, a aplicação deveria ser forçada a tratar essa exceção.
As runtime exceptions são as exceções que herdam de RuntimeException
no java. Quando um método lança uma runtime exception o programador não é obrigado a tratá-la (ao contrário da checked exception). Elas geralmente indicam um erro de programação como acessar uma referência não inicializada (NullPointerException) ou enviar um argumento inválido para o método (IllegalArgumentException).
Agora, para ilustrar as diferenças que existem, vamos ver um código que vocês podem testar:
public class CheckedSaldoInsuficienteException extends Exception {}
public class Conta {
private double saldo;
public void saca(double valor) throws CheckedSaldoInsuficienteException {
if(valor <= this.saldo) {
this.saldo -= valor;
} else {
throw new CheckedSaldoInsuficienteException();
}
}
}
Nesse exemplo, como o CheckedSaldoInsufienteException
é uma checked exception do java, o método saca
da conta é obrigado a declarar que a exceção pode ser lançada (através do throws CheckedSaldoInsuficienteException
). Qualquer classe que tentar chamar esse método saca da Conta
é obrigada pelo compilador do java a tratar a exceção.
public class CaixaEletronico {
public static void main(String[] args){
try{
Conta c = new Conta();
c.saca(500);
} catch (CheckedSaldoInsufienteException e) {
// faz o tratamento
}
}
}
Se removermos o try/catch do código acima, teremos um erro de compilação. Agora vamos ver o que acontece se a exceção lançada for uma unchecked exception:
public class UncheckedSaldoInsuficienteException extends RuntimeException{}
public class Conta {
private double saldo;
public void saca(double valor) {
if(valor <= this.saldo) {
this.saldo -= valor;
} else {
throw new UncheckedSaldoInsuficienteException();
}
}
}
A primeira diferença que pode ser notada, é que como UncheckedSaldoInsuficienteException
herda de RuntimeException
, o código do método saca
não precisa mais colocar o throws
. E no código do CaixaEletronico
não precisamos mais do try/catch
:
public class CaixaEletronico {
public static void main(String[] args){
Conta c = new Conta();
c.saca(500);
}
}
`` public class ValorInvalidoException extends Exception{ private final double valor;
public ValorInvalidoException(double valor) { super("Depósito negativo: " + valor); this.valor = valor; } }
public class TestePrograma { public static void main(String[] args) throws ValorInvalidoException { ContaCorrente cc = new ContaCorrente();
// try { cc.deposita(-1); // } // catch (ValorInvalidoException e){ // System.out.println(e.getMessage()); // } System.out.println(cc.calculaTributos());
//Testando Polimorfismo: Tributavel t = cc; System.out.println(t.calculaTributos()); } } ``
Repare que o código acima compila, mesmo eu comentando o try/catch, pois eu adicionei throws ValorInvalidoException. Eu achei isso curioso e queria entender.
public class ValorInvalidoException extends Exception{ private final double valor; public ValorInvalidoException(double valor) { super("Depósito negativo: " + valor); this.valor = valor; } }
public class TestePrograma { public static void main(String[] args) throws ValorInvalidoException { ContaCorrente cc = new ContaCorrente(); // try { cc.deposita(-1); // } // catch (ValorInvalidoException e){ // System.out.println(e.getMessage()); // } System.out.println(cc.calculaTributos()); //Testando Polimorfismo: Tributavel t = cc; System.out.println(t.calculaTributos()); } }
public class TestePrograma {
public static void main(String[] args) throws ValorInvalidoException {
ContaCorrente cc = new ContaCorrente();
// try {
cc.deposita(-1);
// }
// catch (ValorInvalidoException e){
// System.out.println(e.getMessage());
// }
System.out.println(cc.calculaTributos());
//Testando Polimorfismo:
Tributavel t = cc;
System.out.println(t.calculaTributos());
}
}
public class ValorInvalidoException extends Exception{
private final double valor;
public ValorInvalidoException(double valor) {
super("Depósito negativo: " + valor);
this.valor = valor;
}
}
Agora acho que vai!
Oi Kelvin
Quando você coloca o throws em um código que pode lançar uma checked exception você está basicamente delegando a responsabilidade para quem chamou o método. A exceção ainda precisa ser tratada em algum nível da pilha de execução.
No caso do main, temos a impressão que a exceção foi tratada por que não colocamos o try/catch e o código continua compilando, mas isso é apenas uma ilusão. Nesse caso a exceção é lançada para a JVM e o tratamento implementado pelo java é mostrar a stack trace para o usuário.