Qu'est-ce que SuppressWarnings ("unchecked") en Java?

Parfois, en regardant à travers le code, je vois de nombreuses méthodes spécifier une annotation:

@SuppressWarnings("unchecked")

Qu'est-ce que cela signifie?

371
demandé sur Tom Hawtin - tackline 2009-07-15 10:50:58

9 réponses

Parfois, les génériques Java ne vous permettent tout simplement pas de faire ce que vous voulez, et vous devez dire efficacement au compilateur que ce que vous faites vraiment sera légal au moment de l'exécution.

Je trouve généralement cela pénible quand je me moque d'une interface générique, mais il y a aussi d'autres exemples. Il vaut généralement la peine d'essayer de trouver un moyen d'éviter l'avertissement plutôt que de le supprimer (la FAQ Java Generics aide ici) mais parfois même si est possible, il se plie le code est tellement Déformé que la suppression de l'avertissement est plus nette. Toujours ajouter un commentaire explicatif dans ce cas!

La même FAQ Générique comporte plusieurs sections sur ce sujet, en commençant par "qu'est-ce qu'un avertissement "non coché"?" - il vaut bien une lecture.

360
répondu Jon Skeet 2012-01-26 20:46:31

C'est une annotation pour supprimer les avertissements de compilation concernant les opérations génériques non cochées (pas les exceptions), telles que les conversions. Cela implique essentiellement que le programmeur n'a pas souhaité être informé de ceux-ci dont il est déjà au courant lors de la compilation d'un bit de code particulier.

Vous pouvez en savoir plus sur cette annotation spécifique ici:

Supprimer les Avertissements

En outre, Oracle fournit une documentation tutorielle sur l'utilisation des annotations ici:

Annotations

Comme ils le disent,

"L'avertissement' non coché ' peut se produire lors de l'interface avec du code hérité écrit avant l'avènement des génériques (discuté dans la leçon intitulée Generics)."

43
répondu Ben Lakey 2017-07-27 08:33:08

Cela pourrait également signifier que la version actuelle du système de type Java n'est pas assez bonne pour votre cas. Il y avait plusieurs propositions JSR / hacks pour résoudre ce problème: type tokens, Super Type Tokens , Class.jeter().

Si vous avez vraiment besoin de cette suppression, réduisez-la autant que possible (par exemple, ne la mettez pas sur la classe elle-même ou sur une méthode longue). Un exemple:

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

   Collections.reverse(list);
   return list;
}
17
répondu akarnokd 2009-07-15 07:44:01

Le SuppressWarning annotation est utilisée pour supprimer les avertissements du compilateur pour l'élément. Plus précisément, la catégorie unchecked permet la suppression des avertissements du compilateur générés à la suite de conversions de type non cochées.

9
répondu Brandon E Taylor 2009-07-15 07:02:32

Simplement: c'est un avertissement par lequel le compilateur indique qu'il ne peut pas assurer la sécurité du type.

Méthode de service JPA par exemple:

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

Si je n'ai pas anoté le @ SuppressWarnings ("décoché") ici, il y aurait un problème avec line, où je veux retourner ma liste de résultats.

Dans le raccourci type-safety signifie: un programme est considéré comme sûr s'il compile sans erreurs ni avertissements et ne déclenche aucune ClassCastException inattendue lors de l'exécution.

Je construis sur http://www.angelikalanger.com/GenericsFAQ/FAQSections/Fundamentals.html

7
répondu Daniel Perník 2015-02-07 22:51:53

Vous pouvez supprimer les avertissements du compilateur et dire aux génériques que le code que vous avez écrit est légal selon lui.

Exemple:

@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
répondu s.k.sumaprakash 2012-09-20 12:15:23

Une astuce consiste à créer une interface qui étend une interface de base générique...

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

Ensuite, vous pouvez le vérifier avec instanceof avant la distribution...

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
répondu Brian Edwards 2016-06-23 11:37:20

En Java, les génériques sont implémentés au moyen de l'effacement de type. Par exemple, le code suivant.

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

Est compilé comme suit.

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

Et List.of est défini comme.

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

Qui après effacement de type devient.

static List of(Object e1, Object e2);

Le compilateur n'a aucune idée de ce que sont les types génériques à l'exécution, donc si vous écrivez quelque chose comme ceci.

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

Java Virtual Machine n'a aucune idée de ce que sont les types génériques lors de l'exécution d'un programme, donc cela compile et s'exécute, comme pour la machine virtuelle Java, il s'agit d'un cast de type List (c'est la seule chose qu'il peut vérifier, donc il vérifie seulement cela).

Mais maintenant Ajoutez cette ligne.

Integer hello = actualList.get(0);

Et JVM lancera un ClassCastException inattendu, car le compilateur Java a inséré un cast implicite.

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

Un avertissement unchecked indique à un programmeur qu'une distribution peut amener un programme à lancer une exception ailleurs. La suppression de l'avertissement avec @SuppressWarnings("unchecked") indique au compilateur que le programmeur croit que le code est sûr et ne fera pas exception inattendue.

Pourquoi voudriez-vous faire cela? Le système de type Java n'est pas assez bon pour représenter tous les modèles d'utilisation de type possibles. Parfois, vous savez peut - être qu'un cast est sûr, mais Java ne fournit pas un moyen de le dire-pour cacher des avertissements comme celui-ci, @SupressWarnings("unchecked") peut être utilisé, de sorte qu'un programmeur peut se concentrer sur de vrais Avertissements. Par exemple, Optional.empty() renvoie un singleton pour éviter l'allocation d'options vides qui ne stockent pas de valeur.

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

Ce casting est sûr, comme le la valeur stockée dans un optionnel vide ne peut pas être récupérée, il n'y a donc aucun risque d'exceptions de conversion de classe inattendues.

4
répondu Konrad Borowski 2018-06-01 14:09:17

Pour autant que je sache, pour l'instant cela a à voir avec la suppression des avertissements sur les génériques; les génériques sont une nouvelle construction de programmation non supportée dans les versions JDK antérieures à JDK 5, donc tout mélange des anciennes constructions avec les nouvelles pourrait poser des résultats inattendus.

Le compilateur avertit le programmeur à ce sujet, mais si le programmeur le sait déjà, il peut désactiver ces avertissements redoutés en utilisant SuppressWarnings.

3
répondu BakerTheHacker 2009-07-15 07:03:15