É melhor usar assert ou IllegalArgumentException para parâmetros de método requeridos?

78

Em Java, o que é mais altamente recomendado e por quê? Ambos os tipos lançarão exceções, portanto, a manipulação deles é a mesma. assert é um pouco menor, mas não sei o quanto isso importa.

public void doStuff(Object obj) {
    assert obj != null;
    ...
}

vs

public void doStuff(Object obj) {
    if (obj == null) {
        throw new IllegalArgumentException("object was null");
    }
    ...
}
    
por Daenyth 27.02.2012 / 19:30
fonte

6 respostas

102

CUIDADO!

Afirmações são removidas em tempo de execução, a menos que você especifique explicitamente para " ativar asserções "ao compilar seu código. As Asserções Java não devem ser usadas no código de produção e devem ser restritas a métodos privados (consulte Exceção vs Asserção ), uma vez que se espera que os métodos privados sejam conhecidos e utilizados apenas pelos desenvolvedores. Também assert lançará AssertionError que estende Error não Exception , e que normalmente indica que você tem um erro muito anormal (como "OutOfMemoryError" que é difícil de recuperar, não é?) que não se espera que você seja capaz de tratar.

Remova o sinalizador "enable assertions" e verifique com um depurador e você verá que não será executado a chamada ao IllegalArgumentException ... já que esse código não foi compilado (novamente, quando "ea" for removido )

É melhor usar a segunda construção para métodos públicos / protegidos, e se você quiser algo que é feito em uma linha de código, há pelo menos uma maneira que eu conheço. Eu pessoalmente uso o Spring Framework Assert class que possui alguns métodos para verificar argumentos e que lançam "IllegalArgumentException" na falha. Basicamente, o que você faz é:

Assert.notNull(obj, "object was null");

... Que de fato executará exatamente o mesmo código que você escreveu no seu segundo exemplo. Existem alguns outros métodos úteis, como hasText , hasLength lá.

Eu não gosto de escrever mais código do que o necessário, então fico feliz quando reduzo o número de linhas escritas por 2 (2 linhas > 1 linha): -)

    
por 27.02.2012 / 19:43
fonte
41

Você precisa usar uma exceção. Usar uma afirmação seria um uso incorreto do recurso.

As exceções não verificadas são projetadas para detectar erros de programação dos usuários da sua biblioteca, enquanto as asserções são projetadas para detectar erros na sua própria lógica. Esses são problemas separados que não devem ser misturados.

Por exemplo, uma afirmação

assert myConnection.isConnected();

significa "Eu sei que cada caminho de código que leva a esta asserção assegura que myConnection esteja conectado; se o código acima falhar em obter uma conexão válida, ele deve ter lançado uma exceção ou retorno antes de chegar a este ponto." p>

Por outro lado, um cheque

if (!myConnection.isConnected()) {
    throw new IllegalArgumentException("connection is not established");
}

significa que "Chamar minha biblioteca sem estabelecer uma conexão é um erro de programação".

    
por 27.02.2012 / 20:09
fonte
9

Se você estiver escrevendo uma função que não permite null como um valor de parâmetro válido, adicione o @Nonnull anotar a assinatura e usar Objects.requireNonNull para verificar se o argumento é null e lançar um NullPointerException se for. A anotação @Nonnull é para documentação e fornecerá avisos úteis em tempo de compilação em alguns casos. Isso não impede que null seja passado em tempo de execução.

void doStuff(@Nonnull Object obj) {
    Objects.requireNonNull(obj, "obj must not be null");

    // do stuff...
}
    
por 10.10.2017 / 20:37
fonte
2

Eu sempre prefiro lançar IllegalArgumentException em cima de asserções.

As asserções são usadas principalmente na JUnit ou em outras ferramentas de teste para verificar / confirmar os resultados do teste. Por isso, pode dar uma impressão falsa para outros programadores que o seu método é um método de teste.

Também faz sentido lançar IllegalArgumentException quando um método foi aprovado em um argumento ilegal ou inapropriado . Isso é mais consistente com a convenção Exception Handling seguida pelos desenvolvedores Java.

    
por 22.02.2013 / 12:53
fonte
1

IMO o segundo é um pouco melhor porque traz mais informações e pode ser ainda mais extendido (por exemplo, estendendo a classe de exceção) para ser ainda mais informativo, também não usa comparação negativa que é mais fácil de entender.

    
por 27.02.2012 / 19:38
fonte
1

Eu não uso muito aserts, mas uma abordagem comum com o Lombock @NonNull: link

Implementação do Lombok:      import lombok.NonNull;

public class NonNullExample extends Something {
  private String name;

  public NonNullExample(@NonNull Person person) {
    super("Hello");
    this.name = person.getName();
  }
}

Versão Java:

 import lombok.NonNull;

public class NonNullExample extends Something {
  private String name;

  public NonNullExample(@NonNull Person person) {
    super("Hello");
    if (person == null) {
      throw new NullPointerException("person");
    }
    this.name = person.getName();
  }
}

O Lombok é uma biblioteca muito legal que eu uso em todos os lugares

    
por 19.11.2017 / 20:45
fonte