web-dev-qa-db-fra.com

Qu'est-ce que SuppressWarnings ("décoché") en Java?

Parfois, lorsque je regarde dans le code, de nombreuses méthodes spécifient une annotation:

@SuppressWarnings("unchecked")

Qu'est-ce que ça veut dire?

416
jojo

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

Je trouve généralement cela pénible lorsque 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'alerte plutôt que de la supprimer (le FAQ de Java Generics aide ici) mais parfois même si est possible, le code est tellement déformé que la suppression de l’avertissement est plus ordonnée. Ajoutez toujours un commentaire explicatif dans ce cas!

Le même générique FAQ comporte plusieurs sections sur ce sujet, commençant par "Qu'est-ce qu'un avertissement" non vérifié "?) - sa lecture en vaut la peine.

393
Jon Skeet

Il s'agit d'une annotation à supprimer des avertissements de compilation relatifs aux opérations génériques non contrôlées (et non aux exceptions), telles que les conversions. Cela implique essentiellement que le programmeur ne souhaite pas en être averti, ce qu'il sait déjà lors de la compilation d'un morceau de code particulier.

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

SuppressWarnings

De plus, Oracle fournit une documentation de tutoriel sur l'utilisation des annotations ici:

Annotations

Comme ils l'ont dit,

"L'avertissement" non vérifié "peut se produire lors de l'interfaçage avec du code hérité écrit avant l'avènement des génériques (décrit dans la leçon intitulée Génériques)."

48
Ben Lakey

Cela pourrait également signifier que la version actuelle du système de type Java ne convient pas à votre cas. Il y avait plusieurs propositions de JSR /hacks pour résoudre ce problème: jetons de type, jetons de type super , Class.cast ().

Si vous avez vraiment besoin de cette suppression, limitez-la le plus possible (par exemple, ne la placez 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;
}
19
akarnokd

L'annotation SuppressWarning est utilisée pour supprimer les avertissements du compilateur pour l'élément annoté. Plus précisément, la catégorie unchecked permet de supprimer les avertissements du compilateur générés à la suite de transtypages de types non contrôlés.

9
Brandon E Taylor

Simplement: C'est un avertissement par lequel le compilateur indique qu'il ne peut pas garantir 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'annotais pas le @SuppressWarnings ("non coché") ici, il y aurait un problème avec line, où je veux retourner ma liste de résultats.

En raccourci, sécurité de type signifie: Un programme est considéré comme étant à sécurité de type s'il compile sans erreurs ni avertissements et s'il ne génère pas d'exceptions ClassCastException inattendues au moment de l'exécution.

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

8
Daniel Perník

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

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

Est compilé à la suivante.

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);

Après l'effacement du type devient.

static List of(Object e1, Object e2);

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

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. Ce dernier est donc compilé et exécuté. Quant à Java Machine virtuelle, il s'agit d'un cast vers le type List (c'est la seule chose il peut vérifier, donc il vérifie seulement que).

Mais maintenant, ajoutez cette ligne.

Integer hello = actualList.get(0);

Et JVM lancera un ClassCastException inattendu, comme le compilateur Java insère une distribution 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 à lever une exception ailleurs. La suppression de l'avertissement avec @SuppressWarnings("unchecked") indique au compilateur que le programmeur estime que le code est sûr et ne provoquera pas d'exceptions inattendues.

Pourquoi voudriez-vous faire ça? Le système de types Java n'est pas assez performant pour représenter tous les modèles d'utilisation de types possibles. Parfois, vous savez peut-être qu'un casting est sûr, mais Java ne fournit pas un moyen de le dire. Pour masquer des avertissements de ce type, @SupressWarnings("unchecked") peut être utilisé, de sorte qu'un programmeur puisse se concentrer sur 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;
}

Cette conversion est sécurisée, car la valeur stockée dans une option facultative vide ne peut pas être extraite, il n'y a donc aucun risque d'exception inattendue dans la conversion de classe.

7
Konrad Borowski

Vous pouvez supprimer les avertissements du compilateur et dire aux génériques que le code que vous avez écrit est légal conformément à celui-ci.

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
s.k.sumaprakash

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 vérifier avec instanceof avant le casting ...

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
Brian Edwards

Pour autant que je sache, il s’agit pour l’instant de supprimer les avertissements concernant les génériques; les génériques sont une nouvelle construction de programmation non prise en charge dans les versions de JDK antérieures à JDK 5, de sorte que tout mélange des anciennes constructions avec les nouvelles pourrait donner lieu à des résultats inattendus.

Le compilateur en avertit le programmeur, mais s'il le sait déjà, il peut désactiver ces avertissements redoutés à l'aide de SuppressWarnings.

3
BakerTheHacker

Un avertissement par lequel le compilateur indique qu'il ne peut pas assurer la sécurité du type. Le terme "non contrôlé" est trompeur. Cela ne signifie pas que l'avertissement est décochée de quelque manière que ce soit. Le terme "décoché" fait référence au fait que le compilateur et le système d'exécution ne disposent pas d'assez d'informations de type pour effectuer toutes les vérifications de type nécessaires pour assurer la sécurité du type. En ce sens, certaines opérations sont "décochées".

L'utilisation de types bruts est la source la plus courante d'avertissements "non contrôlés". Des avertissements "non contrôlés" sont émis lors de l'accès à un objet via une variable de type brut, car le type brut ne fournit pas suffisamment d'informations sur le type pour effectuer toutes les vérifications de type nécessaires.

Exemple (d'avertissement non vérifié en liaison avec des types bruts):

TreeSet set = new TreeSet(); 
set.add("abc");        // unchecked warning 
set.remove("abc");
warning: [unchecked] unchecked call to add(E) as a member of the raw type Java.util.TreeSet 
               set.add("abc");  
                      ^

Lorsque la méthode add est appelée, le compilateur ne sait pas s'il est prudent d'ajouter un objet String à la collection. Si TreeSet est une collection qui contient String s (ou un de ses supertypes), il est alors sécurisé. Mais à partir des informations de type fournies par le type brut TreeSet, le compilateur ne peut pas le dire. Par conséquent, l'appel est potentiellement dangereux et un avertissement "non contrôlé" est émis.

Des avertissements "non contrôlés" sont également signalés lorsque le compilateur trouve une distribution dont le type cible est un type paramétré ou un paramètre de type.

Exemple (d'un avertissement non contrôlé associé à un transtypage en un type paramétré ou une variable de type):

  class Wrapper<T> { 
  private T wrapped ; 
  public Wrapper (T arg) {wrapped = arg;} 
  ... 
  public Wrapper <T> clone() { 
    Wrapper<T> clon = null; 
     try {  
       clon = (Wrapper<T>) super.clone(); // unchecked warning 
     } catch (CloneNotSupportedException e) {  
       throw new InternalError();  
     } 
     try {  
       Class<?> clzz = this.wrapped.getClass(); 
       Method   meth = clzz.getMethod("clone", new Class[0]); 
       Object   dupl = meth.invoke(this.wrapped, new Object[0]); 
       clon.wrapped = (T) dupl; // unchecked warning 
     } catch (Exception e) {} 
     return clon; 
  } 
} 
warning: [unchecked] unchecked cast 
found   : Java.lang.Object 
required: Wrapper <T> 
                  clon = ( Wrapper <T>)super.clone();  
                                                ^ 
warning: [unchecked] unchecked cast 
found   : Java.lang.Object 
required: T 
                  clon. wrapped = (T)dupl;

Un transtypage dont le type de cible est un type paramétré (caractère générique concret ou délimité) ou un paramètre de type n'est pas sûr, si une vérification de type dynamique au moment de l'exécution est impliquée. Au moment de l'exécution, seul le type effacement est disponible, pas le type statique exact visible dans le code source. Par conséquent, la partie d'exécution de la conversion est effectuée en fonction du type effacement, et non du type statique exact.

Dans l'exemple, le transtypage vers Wrapper vérifie si l'objet renvoyé par super.clone est un wrapper, et non s'il s'agit d'un wrapper avec un type de membre particulier. De même, les transtors vers le paramètre de type T sont convertis en type Object au moment de l'exécution, et probablement optimisés. En raison de l'effacement du type, le système d'exécution n'est pas en mesure d'effectuer d'autres vérifications de type utiles au moment de l'exécution.

D'une certaine manière, le code source est trompeur, car il suggère qu'une conversion vers le type de cible respectif est effectuée, alors que la partie dynamique de la conversion vérifie uniquement l'effacement du type du type cible. Un avertissement "non vérifié" est émis pour attirer l’attention du programmeur sur ce décalage entre les aspects statique et dynamique de la distribution.

Veuillez vous référer à: Qu'est-ce qu'un avertissement "non vérifié"?

1
Raghu K Nair

L'annotation @SuppressWarnings est l'une des trois annotations intégrées disponibles dans JDK. Elle est ajoutée aux côtés @Override et @Deprecated dans Java 1.5.

@SuppressWarnings indique au compilateur d'ignorer ou de supprimer l'avertissement du compilateur spécifié dans l'élément annoté et tous les éléments de programme à l'intérieur de cet élément. Par exemple, si une classe est annotée pour supprimer un avertissement particulier, un avertissement généré dans une méthode à l'intérieur de cette classe sera également séparé.

Vous avez peut-être vu @SuppressWarnings ("décoché") et @SuppressWarnings ("serial"), deux des exemples les plus populaires d'annotation @SuppressWarnings. Former est utilisé pour supprimer les avertissements générés en raison d'une diffusion non contrôlée, tandis que les derniers avertissements rappellent l'ajout de SerialVersionUID dans une classe Serializable.

En savoir plus: https://javarevisited.blogspot.com/2015/09/what-is-suppresswarnings-annotation-in-Java-unchecked-raw-serial.html#ixzz5rqQaOLUa

0
Majid Roustaei