¿Qué es SuppressWarnings ("unchecked") en Java?


En algún momento al mirar a través del código, veo que muchos métodos especifican una anotación:

@SuppressWarnings("unchecked")

¿Qué significa esto?

Author: Tom Hawtin - tackline, 2009-07-15

9 answers

A veces Java generics simplemente no te permite hacer lo que quieres, y necesitas decirle efectivamente al compilador que lo que estás haciendo realmente será legal en el momento de la ejecución.

Normalmente encuentro esto un dolor cuando me estoy burlando de una interfaz genérica, pero también hay otros ejemplos. Por lo general, vale la pena tratar de encontrar una manera de evitar la advertencia en lugar de suprimirla (el Java Generics FAQ ayuda aquí), pero a veces incluso si es posible, se dobla el código fuera de forma tanto que la supresión de la advertencia es más limpio. Siempre agregue un comentario explicativo en ese caso!

La misma FAQ de genéricos tiene varias secciones sobre este tema, comenzando con "¿Qué es una advertencia "sin marcar"?" - vale la pena leerlo.

 360
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-26 20:46:31

Es una anotación para suprimir las advertencias de compilación sobre operaciones genéricas no verificadas (no excepciones), como los casts. Esencialmente implica que el programador no desea ser notificado acerca de estos que él ya es consciente de la compilación de un pedacito particular de código.

Puede leer más sobre esta anotación específica aquí:

SuppressWarnings

Además, Oracle proporciona documentación tutorial sobre el uso de anotaciones aquí:

Anotaciones

Como dicen,

"La advertencia 'sin marcar' puede ocurrir cuando se interactúa con código heredado escrito antes de la llegada de los genéricos (discutido en la lección titulada Genéricos)."

 43
Author: Ben Lakey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-27 08:33:08

También podría significar que la versión actual del sistema de tipo Java no es lo suficientemente buena para su caso. Hubo varias proposiciones JSR / hacks para arreglar esto: Type tokens, Super Type Tokens, Class.elenco().

Si realmente necesitas esta supresión, acércala lo más posible (por ejemplo, no la pongas en la clase misma o en un método largo). Un ejemplo:

public List<String> getALegacyListReversed() {
   @SuppressWarnings("unchecked") List<String> list =
       (List<String>)legacyLibrary.getStringList();

   Collections.reverse(list);
   return list;
}
 17
Author: akarnokd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-15 07:44:01

La anotación SuppressWarning se usa para suprimir las advertencias del compilador para el elemento anotado. Específicamente, la categoría unchecked permite la supresión de las advertencias del compilador generadas como resultado de casts de tipo sin marcar.

 9
Author: Brandon E Taylor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-15 07:02:32

Simplemente: Es una advertencia mediante la cual el compilador indica que no puede garantizar la seguridad de tipos.

Método de servicio JPA por ejemplo:

@SuppressWarnings("unchecked")
public List<User> findAllUsers(){
    Query query = entitymanager.createQuery("SELECT u FROM User u");
    return (List<User>)query.getResultList();
}

Si no anotara el @SuppressWarnings("unchecked") aquí, tendría un problema con line, donde quiero devolver mi lista de resultados.

En atajo type-safety significa: Un programa se considera type-safe si compila sin errores y advertencias y no genera ningún clascastexception s inesperado en tiempo de ejecución.

Construyo el http://www.angelikalanger.com/GenericsFAQ/FAQSections/Fundamentals.html

 7
Author: Daniel Perník,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-07 22:51:53

Puede suprimir las advertencias del compilador y decirle a los genéricos que el código que ha escrito es legal de acuerdo con él.

Ejemplo:

@SuppressWarnings("unchecked")
public List<ReservationMealPlan> retreiveMealPlan() {
     List<ReservationMealPlan> list=new ArrayList<ReservationMealPlan>();
    TestMenuService testMenuService=new TestMenuService(em, this.selectedInstance);
    list = testMenuService.getMeal(reservationMealPlan);
    return list;
 }
 5
Author: s.k.sumaprakash,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-20 12:15:23

Un truco es crear una interfaz que extienda una interfaz base genérica...

public interface LoadFutures extends Map<UUID, Future<LoadResult>> {}

Entonces puedes comprobarlo con instanceof antes del lanzamiento...

Object obj = context.getAttribute(FUTURES);
if (!(obj instanceof LoadFutures)) {
    String format = "Servlet context attribute \"%s\" is not of type "
            + "LoadFutures. Its type is %s.";
    String msg = String.format(format, FUTURES, obj.getClass());
    throw new RuntimeException(msg);
}
return (LoadFutures) obj;
 5
Author: Brian Edwards,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-23 11:37:20

En Java, los genéricos se implementan mediante el tipo erasure. Por ejemplo, el siguiente código.

List<String> hello = List.of("a", "b");
String example = hello.get(0);

Se compila de la siguiente manera.

List hello = List.of("a", "b");
String example = (String) hello.get(0);

Y List.of se define como.

static <E> List<E> of(E e1, E e2);

Que después del tipo se convierte en borrado.

static List of(Object e1, Object e2);

El compilador no tiene idea de cuáles son los tipos genéricos en tiempo de ejecución, así que si escribes algo como esto.

Object list = List.of("a", "b");
List<Integer> actualList = (List<Integer>) list;

Java Virtual Machine no tiene idea de qué tipos genéricos son mientras se ejecuta un programa, por lo que este compila y se ejecuta, como para Java Virtual Machine, este es un tipo cast to List (esto es lo único que puede verificar, por lo que solo verifica eso).

Pero ahora añade esta línea.

Integer hello = actualList.get(0);

Y JVM lanzará un inesperado ClassCastException, ya que el compilador Java insertó un cast implícito.

java.lang.ClassCastException: java.base/java.lang.String cannot be cast to java.base/java.lang.Integer

Una advertencia unchecked le dice a un programador que un cast puede causar que un programa lance una excepción en otro lugar. Suprimiendo la advertencia con @SuppressWarnings("unchecked") le dice al compilador que el programador cree que el código es seguro y no causará excepciones inesperadas.

¿Por qué querrías hacer eso? El sistema de tipos Java no es lo suficientemente bueno para representar todos los patrones de uso de tipos posibles. A veces puede saber que un cast es seguro, pero Java no proporciona una manera de decirlo - para ocultar advertencias como esta, se puede usar @SupressWarnings("unchecked"), para que un programador pueda centrarse en advertencias reales. Por ejemplo, Optional.empty() devuelve un singleton para evitar la asignación de opciones vacías que no almacenan un valor.

private static final Optional<?> EMPTY = new Optional<>();
public static<T> Optional<T> empty() {
    @SuppressWarnings("unchecked")
    Optional<T> t = (Optional<T>) EMPTY;
    return t;
}

Este molde es seguro, ya que el el valor almacenado en una opción vacía no se puede recuperar, por lo que no hay riesgo de excepciones inesperadas de transmisión de clases.

 4
Author: Konrad Borowski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-01 14:09:17

Por lo que sé, por ahora tiene que ver con la supresión de advertencias sobre genéricos; los genéricos son una nueva construcción de programación no soportada en versiones JDK anteriores a JDK 5, por lo que cualquier mezcla de las viejas construcciones con las nuevas podría plantear algunos resultados inesperados.

El compilador advierte al programador al respecto, pero si el programador ya lo sabe, puede desactivar esas temidas advertencias usando SuppressWarnings.

 3
Author: BakerTheHacker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-15 07:03:15