Diferença entre Throw e Throws em Java
1. Introdução
Neste tutorial, vamos dar uma olhada emthrowethrows em Java. Explicaremos quando devemos usar cada um deles.
A seguir, mostraremos alguns exemplos de seu uso básico.
2. Throw eThrows
Vamos começar com uma introdução rápida. Essas palavras-chave estão relacionadas ao tratamento de exceções. Exceptions are raised when the normal of flow of our application is disrupted.
Pode haver várias razões. Um usuário pode enviar os dados de entrada incorretos. Podemos perder uma conexão ou outra situação inesperada pode ocorrer. O manuseio de boas exceções é essencial para manter nosso aplicativo funcionando após a aparição daqueles momentos desagradáveis.
We use throw keyword to explicitly throw an exception do código. Pode ser qualquer método ou bloco estático. Essa exceção deve ser uma subclasse deThrowable. Além disso, pode ser a própriaThrowable. Não podemos lançar múltiplas exceções com um únicothrow.
A palavra-chaveThrows pode ser colocada na declaração do método. It denotes which exceptions can be thrown from this method. Devemos tratar essas exceções com try-catch.
Essas duas palavras-chave não são intercambiáveis!
3. Throw em Java
Vamos dar uma olhada em um exemplo básico com o lançamento de uma exceção do método.
Em primeiro lugar, imagine que estamos escrevendo uma calculadora simples. Uma das operações aritméticas básicas é a divisão. Por esse motivo, fomos solicitados a implementar esse recurso:
public double divide(double a, double b) {
return a / b;
}
Como não podemos dividir por zero, precisamos adicionar algumas modificações ao nosso código existente. Parece que é um bom momento para levantar uma exceção.
Vamos fazer isso:
public double divide(double a, double b) {
if (b == 0) {
throw new ArithmeticException("Divider cannot be equal to zero!");
}
return a / b;
}
Como você pode ver, usamosArithmeticException para atender perfeitamente às nossas necessidades. Podemos passar um único parâmetro construtorString que é uma mensagem de exceção.
3.1. Boas práticas
We should always prefer the most specific exception. Precisamos encontrar uma classe que se adapte melhor ao nosso evento excepcional. Por exemplo, lanceNumberFormatException enão em vez deIllegalArgumentException. . Devemos evitar lançar umException não específico.
Por exemplo, há uma classeInteger no pacotejava.lang. Vamos dar uma olhada na declaração do método de fábrica:
public static Integer valueOf(String s) throws NumberFormatException
É um método de fábrica estático que criaInteger instância deString. ; no caso de entrada erradaString, o método irá lançarNumberFormatException.
A good idea is to define our own, more descriptive exception. Em nossa classeCalculator que poderia ser, por exemploDivideByZeroException.
Vamos dar uma olhada no exemplo de implementação:
public class DivideByZeroException extends RuntimeException {
public DivideByZeroException(String message) {
super(message);
}
}
3.2. Agrupando uma exceção existente
Às vezes, queremos agrupar uma exceção existente na exceção definida por nós.
Vamos começar definindo nossa própria exceção:
public class DataAcessException extends RuntimeException {
public DataAcessException(String message, Throwable cause) {
super(message, cause);
}
}
O construtor leva dois parâmetros: mensagem de exceção e uma causa, que pode ser qualquer subclasse deThrowable.
Vamos escrever uma implementação falsa para a funçãofindAll() :
public List findAll() throws SQLException {
throw new SQLException();
}
Agora, emSimpleService, vamos chamar uma função de repositório, que pode resultar emSQLException:
public void wrappingException() {
try {
personRepository.findAll();
} catch (SQLException e) {
throw new DataAccessException("SQL Exception", e);
}
}
Estamos jogando novamenteSQLException embrulhado em nossa própria exceção chamadaDataAccessException. Tudo é verificado pelo seguinte teste:
@Test
void whenSQLExceptionIsThrown_thenShouldBeRethrownWithWrappedException() {
assertThrows(DataAccessException.class,
() -> simpleService.wrappingException());
}
Há duas razões para fazer isso. Primeiro, usamos o agrupamento de exceções, porque o restante do código não precisa saber sobre todas as exceções possíveis no sistema.
Os componentes de nível superior também não precisam conhecer os componentes de nível inferior, nem as exceções que eles lançam.
3.3. Captura múltipla com Java
Às vezes, os métodos que usamos podem gerar muitas exceções diferentes.
Vamos dar uma olhada em um bloco try-catch mais extenso:
try {
tryCatch.execute();
} catch (ConnectionException | SocketException ex) {
System.out.println("IOException");
} catch (Exception ex) {
System.out.println("General exception");
}
O métodoexecute pode lançar três exceções:SocketException, ConnectionException, Exception. O primeiro bloco catch irá capturarConnectionException ouSocketException. O segundo bloco de captura capturariaException ou qualquer outra subclasse deException. Lembre-se de quewe should always catch a more detailed exception first.
Podemos trocar a ordem dos nossos blocos de captura. Então, nunca pegaríamosSocketExceptioneConnectionException porque tudo irá para a captura comException.
4. Throws em Java
Adicionamosthrows à declaração do método.
Vamos dar uma olhada em uma de nossas declarações de método anteriores:
public static void execute() throws SocketException, ConnectionException, Exception
The method may throw multiple exceptions. Eles são separados por vírgulas no final de uma declaração de método. Podemos colocar exceções verificadas e não verificadas emthrows. . Descrevemos a diferença entre elas abaixo.
4.1. Exceções marcadas e desmarcadas
A checked exception means that it’s checked at the compile time. Observe que devemos lidar com essa exceção. Caso contrário, um método deve especificar uma exceção usando a palavra-chavethrows.
As exceções verificadas mais comuns sãoIOException, FileNotFoundException, ParseException. FileNotFoundException . Podem ser lançadas quando criamosFileInputStream deFile.
Este é um pequeno exemplo:
File file = new File("not_existing_file.txt");
try {
FileInputStream stream = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Podemos evitar o uso do bloco try-catch adicionandothrows à declaração do método:
private static void uncheckedException() throws FileNotFoundException {
File file = new File("not_existing_file.txt");
FileInputStream stream = new FileInputStream(file);
}
Infelizmente, uma função de nível superior ainda precisa lidar com essa exceção. Caso contrário, temos que colocar esta exceção na declaração do método comthrows keyword.
Ao contrário,unchecked exceptions aren’t checked at the compile time.
As exceções não verificadas mais comuns são:ArrayIndexOutOfBoundsException, IllegalArgumentException, NullPointerException.
Unchecked exceptions are thrown during runtime. O código a seguir lançará umNullPointerException. Provavelmente é uma das exceções mais comuns em Java.
Chamar um método em uma referência nula resultará nesta exceção:
public void runtimeNullPointerException() {
String a = null;
a.length();
}
Vamos verificar esse comportamento no teste:
@Test
void whenCalled_thenNullPointerExceptionIsThrown() {
assertThrows(NullPointerException.class,
() -> simpleService.runtimeNullPointerException());
}
Lembre-se de que este código e teste não fazem muito sentido. É apenas para fins de aprendizagem explicar as exceções de tempo de execução.
Em Java, cada subclasse deErroreRuntimeException é uma exceção não verificada. Uma exceção verificada é todo o resto no sclassThrowable .
5. Conclusão
Neste artigo, discutimos a diferença entre duas palavras-chave Java:throwethrows. Passamos pelo uso básico e conversamos um pouco sobre as boas práticas. Então falamos sobre exceções verificadas e não verificadas.
Como sempre, o código-fonte pode ser encontradoon our GitHub.
Se você quiser se aprofundar no tratamento de exceções em Java, dê uma olhada em nosso artigoabout Java exceptions.