personalizar ejemplo definicion java assertions

ejemplo - personalizar jtabbedpane java



¿Qué hace la palabra clave de afirmación de Java y cuándo se debe utilizar? (18)

¿Qué hace la palabra clave assert en Java?

Veamos el bytecode compilado.

Concluiremos que:

public class Assert { public static void main(String[] args) { assert System.currentTimeMillis() == 0L; } }

genera casi exactamente el mismo código de bytes que:

public class Assert { static final boolean $assertionsDisabled = !Assert.class.desiredAssertionStatus(); public static void main(String[] args) { if (!$assertionsDisabled) { if (System.currentTimeMillis() != 0L) { throw new AssertionError(); } } } }

donde Assert.class.desiredAssertionStatus() es true cuando -ea se pasa en la línea de comando, y en caso contrario, es falso.

Utilizamos System.currentTimeMillis() para asegurarnos de que no se optimice ( assert true; did).

El campo sintético se genera de modo que Java solo necesita llamar a Assert.class.desiredAssertionStatus() una vez en el tiempo de carga, y luego almacena el resultado allí. Ver también: ¿Cuál es el significado de "sintético estático"?

Podemos verificar que con:

javac Assert.java javap -c -constants -private -verbose Assert.class

Con Oracle JDK 1.8.0_45, se generó un campo estático sintético (ver también: ¿Cuál es el significado de "sintético estático"? ):

static final boolean $assertionsDisabled; descriptor: Z flags: ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC

junto con un inicializador estático:

0: ldc #6 // class Assert 2: invokevirtual #7 // Method java/lang Class.desiredAssertionStatus:()Z 5: ifne 12 8: iconst_1 9: goto 13 12: iconst_0 13: putstatic #2 // Field $assertionsDisabled:Z 16: return

y el método principal es:

0: getstatic #2 // Field $assertionsDisabled:Z 3: ifne 22 6: invokestatic #3 // Method java/lang/System.currentTimeMillis:()J 9: lconst_0 10: lcmp 11: ifeq 22 14: new #4 // class java/lang/AssertionError 17: dup 18: invokespecial #5 // Method java/lang/AssertionError."<init>":()V 21: athrow 22: return

Concluimos que:

  • no hay soporte a nivel de bytecode para assert : es un concepto de lenguaje Java
  • assert podría emularse bastante bien con las propiedades del sistema -Pcom.me.assert=true para reemplazar -ea en la línea de comandos, y throw new AssertionError() un throw new AssertionError() .

¿Cuáles son algunos ejemplos de la vida real para entender el papel clave de las afirmaciones?


Además de todas las excelentes respuestas proporcionadas aquí, la guía de programación oficial de Java SE 7 tiene un manual bastante conciso sobre el uso de assert ; con varios ejemplos puntuales de cuándo es una buena idea (y, lo que es más importante, mala) usar aserciones y en qué se diferencia de las excepciones de lanzamiento.

Link


Afirmar es muy útil cuando se desarrolla. Lo usas cuando algo no puede suceder si tu código está funcionando correctamente. Es fácil de usar y puede permanecer en el código para siempre, porque se apagará en la vida real.

Si existe alguna posibilidad de que la afección pueda ocurrir en la vida real, debe manejarlo.

Me encanta, pero no sé cómo activarlo en Eclipse / Android / ADT. Parece estar apagado incluso al depurar. (Hay un hilo en esto, pero se refiere a ''Java vm'', que no aparece en la configuración de ejecución de ADT).


Aquí está el caso de uso más común. Supongamos que está activando un valor de enumeración:

switch (fruit) { case apple: // do something break; case pear: // do something break; case banana: // do something break; }

Mientras manejas cada caso, estás bien. Pero algún día, alguien agregará higo a su enumeración y se olvidará de agregarlo a su declaración de cambio. Esto produce un error que puede ser difícil de detectar, ya que los efectos no se notarán hasta después de que haya dejado la instrucción de cambio. Pero si escribes tu interruptor de esta manera, puedes atraparlo inmediatamente:

switch (fruit) { case apple: // do something break; case pear: // do something break; case banana: // do something break; default: assert false : "Missing enum value: " + fruit; }


Aquí hay una afirmación que escribí en un servidor para un proyecto Hibernate / SQL. Un bean entidad tenía dos propiedades efectivamente booleanas, llamadas isActive e isDefault. Cada uno podría tener un valor de "Y" o "N" o nulo, que se trató como "N". Queremos asegurarnos de que el cliente del navegador esté limitado a estos tres valores. Entonces, en mis configuradores para estas dos propiedades, agregué esta afirmación:

assert new HashSet<String>(Arrays.asList("Y", "N", null)).contains(value) : value;

Note lo siguiente.

  1. Esta afirmación es solo para la fase de desarrollo. Si el cliente envía un valor incorrecto, lo capturaremos temprano y lo arreglaremos, mucho antes de que lleguemos a la producción. Las afirmaciones son para los defectos que puede detectar temprano.

  2. Esta afirmación es lenta e ineficiente. Esta bien. Las afirmaciones son libres de ser lentas. No nos importa porque son herramientas de desarrollo solamente. Esto no ralentizará el código de producción porque se deshabilitarán las aserciones. (Hay algún desacuerdo sobre este punto, que veré más adelante). Esto lleva a mi siguiente punto.

  3. Esta afirmación no tiene efectos secundarios. Podría haber probado mi valor contra un Conjunto final estático no modificable, pero ese conjunto se habría mantenido en producción, donde nunca se utilizaría.

  4. Esta afirmación existe para verificar el correcto funcionamiento del cliente. Entonces, cuando lleguemos a la producción, estaremos seguros de que el cliente está funcionando correctamente, por lo que podemos desactivar la afirmación de forma segura.

  5. Algunas personas preguntan esto: si la afirmación no es necesaria en la producción, ¿por qué no eliminarla cuando haya terminado? Porque aún los necesitarás cuando comiences a trabajar en la próxima versión.

Algunas personas han argumentado que nunca debes usar aserciones, porque nunca puedes estar seguro de que todos los errores han desaparecido, por lo que necesitas mantenerlos cerca incluso en producción. Y, por lo tanto, no tiene sentido usar la declaración de afirmación, ya que la única ventaja de las afirmaciones es que puede desactivarlas. Por lo tanto, de acuerdo con este pensamiento, debería (casi) nunca usar aserciones. Estoy en desacuerdo. Es cierto que si una prueba pertenece a producción, no debe usar una aserción. Pero esta prueba no pertenece a la producción. Este es para detectar un error que no es probable que llegue a la producción, por lo que puede desactivarse de forma segura cuando haya terminado.

Por cierto, podría haberlo escrito así:

assert value == null || value.equals("Y") || value.equals("N") : value;

Esto está bien solo para tres valores, pero si el número de valores posibles aumenta, la versión HashSet se vuelve más conveniente. Elegí la versión HashSet para hacer mi punto sobre la eficiencia.


Las aserciones están deshabilitadas por defecto. Para habilitarlos debemos ejecutar el programa con las opciones -ea (la granularidad puede variar). Por ejemplo, java -ea AssertionsDemo .

Hay dos formatos para usar aserciones:

  1. Simple: por ejemplo. assert 1==2; // This will raise an AssertionError assert 1==2; // This will raise an AssertionError .
  2. Mejor: assert 1==2: "no way.. 1 is not equal to 2"; Esto generará un error de aserción con el mensaje dado que también se muestra y por lo tanto es mejor. Aunque la sintaxis real es assert expr1:expr2 donde expr2 puede ser cualquier expresión que devuelva un valor, lo he usado más a menudo solo para imprimir un mensaje.

Las aserciones se utilizan para verificar las condiciones posteriores y las condiciones previas de "nunca deben fallar". El código correcto nunca debe fallar una aserción; cuando se activan, deben indicar un error (con suerte en un lugar cercano al lugar real del problema).

Un ejemplo de una aserción podría ser verificar que se llame a un grupo particular de métodos en el orden correcto (por ejemplo, que hasNext() se llame antes de next() en un Iterator ).


Las aserciones son una herramienta en fase de desarrollo para detectar errores en su código. Están diseñados para ser removidos fácilmente, por lo que no existirán en el código de producción. Por lo tanto, las afirmaciones no son parte de la "solución" que usted entrega al cliente. Son controles internos para asegurarse de que las suposiciones que está haciendo son correctas. El ejemplo más común es probar para nulo. Muchos métodos se escriben así:

void doSomething(Widget widget) { if (widget != null) { widget.someMethod(); // ... ... // do more stuff with this widget } }

Muy a menudo, en un método como este, el widget simplemente nunca debe ser nulo. Entonces, si es nulo, hay un error en su código en algún lugar que necesita rastrear. Pero el código de arriba nunca te dirá esto. Entonces, en un esfuerzo bien intencionado para escribir un código "seguro", también estás ocultando un error. Es mucho mejor escribir código como este:

/** * @param Widget widget Should never be null */ void doSomething(Widget widget) { assert widget != null; widget.someMethod(); // ... ... // do more stuff with this widget }

De esta manera, estarás seguro de atrapar este error temprano. (También es útil especificar en el contrato que este parámetro nunca debe ser nulo). Asegúrese de activar las afirmaciones cuando pruebe su código durante el desarrollo. (Y persuadir a sus colegas para que hagan esto, también es a menudo difícil, lo que me parece muy molesto).

Ahora, algunos de sus colegas se opondrán a este código, argumentando que aún debe poner la verificación nula para evitar una excepción en la producción. En ese caso, la afirmación sigue siendo útil. Puedes escribirlo así:

void doSomething(Widget widget) { assert widget != null; if (widget != null) { widget.someMethod(); // ... ... // do more stuff with this widget } }

De esta manera, sus colegas estarán felices de que la comprobación de nulos esté ahí para el código de producción, pero durante el desarrollo, ya no estará ocultando el error cuando el widget es nulo.

Aquí hay un ejemplo del mundo real: una vez escribí un método que comparaba dos valores arbitrarios para la igualdad, donde cualquiera de los valores podría ser nulo:

/** * Compare two values using equals(), after checking for null. * @param thisValue (may be null) * @param otherValue (may be null) * @return True if they are both null or if equals() returns true */ public static boolean compare(final Object thisValue, final Object otherValue) { boolean result; if (thisValue == null) { result = otherValue == null; } else { result = thisValue.equals(otherValue); } return result; }

Este código delega el trabajo del método equals() en el caso de que este Valor no sea nulo. Pero asume que el método equals() cumple correctamente el contrato de equals() al manejar adecuadamente un parámetro nulo.

Un colega se opuso a mi código y me dijo que muchas de nuestras clases tienen métodos buggy equals() que no prueban el valor nulo, por lo que debería poner ese control en este método. Es discutible si esto es prudente, o si deberíamos forzar el error, para poder localizarlo y solucionarlo, pero lo aplazé a mi colega y puse un cheque nulo, que he marcado con un comentario:

public static boolean compare(final Object thisValue, final Object otherValue) { boolean result; if (thisValue == null) { result = otherValue == null; } else { result = otherValue != null && thisValue.equals(otherValue); // questionable null check } return result; }

La verificación adicional aquí, other != null , solo es necesaria si el método equals() no puede verificar la null como lo exige su contrato.

En lugar de entablar un debate infructuoso con mi colega sobre la conveniencia de dejar que el código de buggy permanezca en nuestra base de código, simplemente pongo dos aserciones en el código. Estas afirmaciones me lo harán saber, durante la fase de desarrollo, si una de nuestras clases no implementa equals() correctamente, así puedo solucionarlo:

public static boolean compare(final Object thisValue, final Object otherValue) { boolean result; if (thisValue == null) { result = otherValue == null; assert otherValue == null || otherValue.equals(null) == false; } else { result = otherValue != null && thisValue.equals(otherValue); assert thisValue.equals(null) == false; } return result; }

Los puntos importantes a tener en cuenta son estos:

  1. Las afirmaciones son solo herramientas de la fase de desarrollo.

  2. El punto de una afirmación es hacerle saber si hay un error, no solo en su código, sino en su base de código . (Las afirmaciones aquí en realidad marcarán errores en otras clases).

  3. Incluso si mi colega confiaba en que nuestras clases estaban escritas correctamente, las aseveraciones aquí serían útiles. Se agregarán nuevas clases que podrían fallar en la prueba de nulo, y este método puede marcar esos errores para nosotros.

  4. En el desarrollo, siempre debe activar las aserciones, incluso si el código que ha escrito no usa aserciones. Mi IDE está configurado para hacer esto siempre por defecto para cualquier nuevo ejecutable.

  5. Las afirmaciones no cambian el comportamiento del código en producción, por lo que mi colega está contento de que haya una comprobación nula y de que este método se ejecutará correctamente incluso si el método equals() tiene errores. Estoy contento porque atraparé cualquier método buggy equals() en desarrollo.

Además, debe probar su política de aserción colocando una aserción temporal que fallará, de modo que pueda estar seguro de que se le notificará, ya sea a través del archivo de registro o un seguimiento de la pila en la secuencia de salida.


Muchas respuestas buenas que explican lo que hace la palabra clave de afirmación, pero pocas responden a la pregunta real: "¿cuándo se debe utilizar la palabra clave de assert en la vida real?"

La respuesta: casi nunca .

Las afirmaciones, como concepto, son maravillosas. El código bueno tiene muchas declaraciones if (...) throw ... (y sus parientes como Objects.requireNonNull y Math.addExact ). Sin embargo, ciertas decisiones de diseño han limitado en gran medida la utilidad de la propia palabra clave assert .

La idea clave detrás de la palabra clave assert es la optimización prematura, y la característica principal es poder desactivar fácilmente todos los controles. De hecho, las comprobaciones de assert están desactivadas de forma predeterminada.

Sin embargo, es de vital importancia que los controles invariantes se sigan realizando en la producción. Esto se debe a que la cobertura de prueba perfecta es imposible, y todo el código de producción tendrá errores que las aserciones deberían ayudar a diagnosticar y mitigar.

Por lo tanto, el uso de if (...) throw ... debería ser preferido, al igual que se requiere para verificar los valores de los parámetros de los métodos públicos y para lanzar IllegalArgumentException .

Ocasionalmente, uno podría verse tentado a escribir un cheque invariante que tarda un tiempo indeseable en procesarse (y se le llama con la frecuencia suficiente para que importe). Sin embargo, tales controles ralentizarán las pruebas, lo que también es indeseable. Tales cheques que consumen mucho tiempo se escriben generalmente como pruebas unitarias. Sin embargo, a veces puede tener sentido utilizar assert por este motivo.

No lo utilice simplemente porque es más limpio y más bonito que if (...) throw ... (y lo digo con mucho dolor, porque me gusta limpio y bonito). Si no puede ayudarse a sí mismo y puede controlar cómo se inicia su aplicación, no dude en utilizar assert pero siempre habilite aserciones en producción. Es cierto que esto es lo que tiendo a hacer. Estoy presionando para obtener una anotación lombok que hará que assert actúe más como if (...) throw ... Vota por esto aquí.

(Rant: los desarrolladores de JVM eran un grupo de codificadores terriblemente optimizados prematuramente. Es por eso que se enteran de tantos problemas de seguridad en el complemento de Java y JVM. Se negaron a incluir comprobaciones y afirmaciones básicas en el código de producción, y continuamos paga el precio.)


Para resumir (y esto es cierto para muchos lenguajes, no solo para Java):

"assert" se usa principalmente como una ayuda de depuración por los desarrolladores de software durante el proceso de depuración. Los mensajes asertivos nunca deben aparecer. Muchos idiomas proporcionan una opción de tiempo de compilación que hará que todas las "afirmaciones" sean ignoradas, para su uso en la generación de código de "producción".

Las "excepciones" son una forma útil de manejar todo tipo de condiciones de error, ya sea que representen o no errores lógicos, porque, si se encuentra con una condición de error tal que no puede continuar, simplemente puede "lanzarlos al aire "desde donde sea que estés, esperando que alguien más esté listo para" atraparlo ". El control se transfiere en un solo paso, directamente desde el código que lanzó la excepción, directamente al guante del receptor. (Y el receptor puede ver el retroceso completo de las llamadas realizadas).

Además, las personas que llaman de esa subrutina no tienen que verificar si la subrutina tuvo éxito: "si estamos aquí ahora, debe haber tenido éxito, porque de lo contrario, habría lanzado una excepción y no estaríamos aquí ahora". Esta estrategia simple hace que el diseño de código y la depuración sean mucho más fáciles.

Las excepciones permiten convenientemente que las condiciones de error grave sean lo que son: "excepciones a la regla". Y, para que sean manejados por una ruta de código que también es "una excepción a la regla ... " ¡bola voladora!


Supongamos que se supone que debes escribir un programa para controlar una central nuclear. Es bastante obvio que incluso el error más pequeño podría tener resultados catastróficos, por lo tanto, su código debe estar libre de errores (asumiendo que la JVM está libre de errores por el bien del argumento).

Java no es un lenguaje verificable, lo que significa que no puede calcular que el resultado de su operación sea perfecto. La razón principal de esto son los punteros: pueden apuntar a cualquier parte o a ninguna parte, por lo tanto, no pueden calcularse para que tengan este valor exacto, al menos no dentro de un intervalo de código razonable. Dado este problema, no hay manera de probar que su código es correcto en su totalidad. Pero lo que puedes hacer es demostrar que al menos encuentras todos los errores cuando sucede.

Esta idea se basa en el paradigma de Design-by-Contract (DbC): primero define (con precisión matemática) lo que se supone que debe hacer su método, y luego verifique esto probándolo durante la ejecución real. Ejemplo:

// Calculates the sum of a (int) + b (int) and returns the result (int). int sum(int a, int b) { return a + b; }

Si bien esto es bastante obvio para funcionar bien, la mayoría de los programadores no verán el error oculto dentro de este (pista: la Ariane V se bloqueó debido a un error similar). Ahora DbC define que siempre debe verificar la entrada y salida de una función para verificar que funcionó correctamente. Java puede hacer esto a través de aserciones:

// Calculates the sum of a (int) + b (int) and returns the result (int). int sum(int a, int b) { assert (Integer.MAX_VALUE - a >= b) : "Value of " + a + " + " + b + " is too large to add."; final int result = a + b; assert (result - a == b) : "Sum of " + a + " + " + b + " returned wrong sum " + result; return result; }

Si esta función falla alguna vez, lo notará. Sabrá que hay un problema en su código, sabe dónde está y sabe qué lo causó (similar a las Excepciones). Y lo que es aún más importante: deja de ejecutar correctamente cuando sucede para evitar que cualquier código adicional funcione con valores incorrectos y cause daños a cualquier cosa que controle.

Las excepciones de Java son un concepto similar, pero no pueden verificar todo. Si desea aún más verificaciones (al costo de la velocidad de ejecución) necesita usar aserciones. Si lo hace, aumentará su código, pero al final puede entregar un producto en un tiempo de desarrollo sorprendentemente corto (cuanto antes solucione un error, menor será el costo). Y además: si hay algún error dentro de su código, lo detectará. No hay forma de que un error se resbale y cause problemas más adelante.

Esto todavía no es una garantía para el código libre de errores, pero está mucho más cerca de eso que los programas habituales.


Un ejemplo del mundo real, de una clase de pila (de aserción en artículos de Java )

public int pop() { // precondition assert !isEmpty() : "Stack is empty"; return stack[--num]; }


Una afirmación permite detectar defectos en el código. Puede activar las aserciones para las pruebas y la depuración y dejarlas cuando su programa está en producción.

¿Por qué afirmar algo cuando sabes que es verdad? Solo es verdad cuando todo funciona correctamente. Si el programa tiene un defecto, puede que no sea verdad. Detectar esto antes en el proceso le permite saber que algo está mal.

Una declaración de afirmación contiene esta declaración junto con un mensaje de String opcional.

La sintaxis de una aseveración tiene dos formas:

assert boolean_expression; assert boolean_expression: error_message;

Aquí hay algunas reglas básicas que rigen dónde se deben usar las aserciones y dónde no se deben usar. Las afirmaciones se deben utilizar para:

  1. Validación de parámetros de entrada de un método privado. NO para los métodos públicos. public métodos public deberían lanzar excepciones regulares cuando se pasan parámetros incorrectos.

  2. En cualquier parte del programa para garantizar la validez de un hecho que es casi seguro.

Por ejemplo, si está seguro de que solo será 1 o 2, puede usar una aseveración como esta:

... if (i == 1)    { ... } else if (i == 2)    { ... } else { assert false : "cannot happen. i is " + i; } ...

  1. Validación de las condiciones de la publicación al final de cualquier método. Esto significa que, después de ejecutar la lógica de negocios, puede usar aserciones para asegurarse de que el estado interno de sus variables o resultados sea consistente con lo que espera. Por ejemplo, un método que abre un socket o un archivo puede usar una aserción al final para garantizar que el socket o el archivo se abra efectivamente.

Las afirmaciones no se deben utilizar para:

  1. Validación de parámetros de entrada de un método público. Como las aserciones no siempre se pueden ejecutar, se debe usar el mecanismo de excepción regular.

  2. Validación de restricciones en algo que es ingresado por el usuario. Lo mismo que arriba.

  3. No debe utilizarse para efectos secundarios.

Por ejemplo, este no es un uso adecuado porque aquí la aserción se usa por su efecto secundario de llamar al método doSomething() .

public boolean doSomething() { ...     } public void someMethod() {        assert doSomething(); }

El único caso en que esto podría estar justificado es cuando intenta averiguar si las aserciones están habilitadas o no en su código:

boolean enabled = false;     assert enabled = true;     if (enabled) { System.out.println("Assertions are enabled"); } else { System.out.println("Assertions are disabled"); }


assertes una palabra clave. Fue introducido en JDK 1.4. Hay dos tipos de asserts

  1. assertDeclaraciones muy simples
  2. assertDeclaraciones simples .

Por defecto todas las assertdeclaraciones no serán ejecutadas. Si una assertdeclaración recibe un mensaje falso, automáticamente generará un error de aserción.


La afirmación se usa básicamente para depurar la aplicación o se usa en reemplazo del manejo de excepciones para algunas aplicaciones para verificar la validez de una aplicación.

La afirmación funciona en tiempo de ejecución. Un ejemplo simple, que puede explicar todo el concepto de manera muy simple, se encuentra aquí: ¿Qué hace la palabra clave assert en Java? (WikiAnswers).


Se agregaron Assertions (a través de la palabra clave assert ) en Java 1.4. Se utilizan para verificar la corrección de un invariante en el código. Nunca deben activarse en el código de producción, y son indicativos de un error o mal uso de una ruta de código. Se pueden activar en tiempo de ejecución mediante la opción -ea en el comando java , pero no están activadas de forma predeterminada.

Un ejemplo:

public Foo acquireFoo(int id) { Foo result = null; if (id > 50) { result = fooService.read(id); } else { result = new Foo(id); } assert result != null; return result; }


Básicamente, "afirmar verdadero" pasará y "afirmar falso" fallará. Veamos cómo funcionará esto:

public static void main(String[] args) { String s1 = "Hello"; assert checkInteger(s1); } private static boolean checkInteger(String s) { try { Integer.parseInt(s); return true; } catch(Exception e) { return false; } }


Las afirmaciones son cheques que pueden ser desactivados. Rara vez se utilizan. ¿Por qué?

  • No deben usarse para verificar argumentos de métodos públicos, ya que no tiene control sobre ellos.
  • No deben utilizarse para controles simples, result != nullya que dichos controles son muy rápidos y casi no hay nada que guardar.

Entonces, ¿qué queda? Controles costosos de las condiciones que realmente se esperan que sean ciertas. Un buen ejemplo serían las invariantes de una estructura de datos como RB-tree. En realidad, en ConcurrentHashMapJDK8, hay algunas afirmaciones tan significativas para el TreeNodes.

  • Realmente no desea activarlos en producción ya que podrían dominar fácilmente el tiempo de ejecución.
  • Es posible que desee encenderlos o apagarlos durante las pruebas.
  • Definitivamente quieres encenderlos cuando trabajas en el código.