¿Es mejor usar assert o IllegalArgumentException para los parámetros de método requeridos?

78

En Java, ¿cuál es la más recomendada y por qué? Ambos tipos lanzarán excepciones, por lo que en este sentido el manejo de ellos es el mismo. assert es un poco más corto, pero no estoy seguro de cuánto importa.

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

vs

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

6 respuestas

100

¡TEN CUIDADO!

Assertions se eliminan en el tiempo de ejecución a menos que especifique explícitamente que " habilitar aserciones "al compilar su código. Las aserciones de Java no deben usarse en el código de producción y deben restringirse a métodos privados (consulte Excepción contra aserción ), ya que se espera que los métodos privados sean conocidos y utilizados solo por los desarrolladores. También assert lanzará AssertionError que se extiende Error no Exception , y lo que normalmente indica que tiene un error muy anormal (como "OutOfMemoryError", del cual es difícil recuperarse, ¿no es así?) no se espera que pueda tratarlo.

Elimine el indicador "habilitar aserciones", verifique con un depurador y verá que no pisará la llamada de excepción IllegalArgumentException ... ya que este código no se ha compilado (de nuevo, cuando se elimina "ea" )

Es mejor usar la segunda construcción para métodos públicos / protegidos, y si quieres algo que se haga en una línea de código, hay al menos una forma que conozco. Personalmente uso el Spring Framework 's Assert clase que tiene algunos métodos para verificar argumentos y que arroja "IllegalArgumentException" en caso de error. Básicamente, lo que haces es:

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

... que de hecho ejecutará exactamente el mismo código que escribiste en tu segundo ejemplo. Hay algunos otros métodos útiles como hasText , hasLength ahí.

No me gusta escribir más código del necesario, así que me alegro cuando reduzco el número de líneas escritas en 2 (2 líneas > 1 línea) :-)

    
respondido por el Jalayn 27.02.2012 - 19:43
41

Necesitas usar una excepción. El uso de una aserción sería un mal uso de la función.

Las excepciones sin marcar están diseñadas para detectar errores de programación de los usuarios de su biblioteca, mientras que las aserciones están diseñadas para detectar errores en la lógica su propia . Estos son temas separados que no deben mezclarse.

Por ejemplo, una aserción

assert myConnection.isConnected();

significa "Sé que cada ruta de código que conduce a esta aseveración garantiza que myConnection está conectado; si el código anterior no pudo obtener una conexión válida, debería haber lanzado una excepción o devolución antes de llegar a este punto". p>

Por otro lado, un cheque

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

significa que "Llamar a mi biblioteca sin establecer una conexión es un error de programación".

    
respondido por el dasblinkenlight 27.02.2012 - 20:09
7

Si está escribiendo una función que no permite null como un valor de parámetro válido, debe agregar el @Nonnull como anotación a la firma y use Objects.requireNonNull para verificar si el argumento es null y arroja NullPointerException si lo es. La anotación @Nonnull es para documentación y proporcionará advertencias útiles en el momento de la compilación en algunos casos. No evita que se pase null en tiempo de ejecución.

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

    // do stuff...
}
    
respondido por el cambunctious 10.10.2017 - 20:37
2

Siempre prefiero lanzar la excepción IllegalArgumentException sobre las aserciones.

Las aserciones se utilizan principalmente en JUnit u otras herramientas de prueba, para verificar / afirmar los resultados de las pruebas. Por lo tanto, podría dar una falsa impresión a otros desarrolladores de que su método es un método de prueba.

También tiene sentido lanzar la excepción IllegalArgumentException cuando un método ha pasado un argumento ilegal o inapropiado . Esto es más consistente con la convención de manejo de excepciones seguida por los desarrolladores de Java.

    
respondido por el rai.skumar 22.02.2013 - 12:53
1

OMI, el segundo es ligeramente mejor porque brinda más información y podría ampliarse (p. ej., extendiendo la clase de excepción) para que sea aún más informativo, y tampoco usa una comparación negativa, que es más fácil de entender.

    
respondido por el 0lukasz0 27.02.2012 - 19:38
1

No uso mucho las aserciones, pero el enfoque común con Lombock @NonNull es: enlace

Implementación de Lombok:      importar lombok.NonNull;

public class NonNullExample extends Something {
  private String name;

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

versión de 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();
  }
}

Lombok es una muy buena biblioteca que uso en todas partes

    
respondido por el kensai 19.11.2017 - 20:45

Lea otras preguntas en las etiquetas