Réponses:
Parfois, les génériques Java ne vous permettent tout simplement pas de faire ce que vous voulez, et vous devez dire au compilateur que ce que vous faites sera vraiment 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 existe également d'autres exemples. Il est généralement intéressant d' essayer de trouver un moyen d'éviter la mise en garde plutôt que de le supprimer (la FAQ Java Generics aide ici) , mais parfois même si elle est possible, il plie le code de la forme tant que la suppression de l'avertissement est plus propre. Ajoutez toujours un commentaire explicatif dans ce cas!
La même FAQ sur les génériques comporte plusieurs sections sur ce sujet, commençant par "Qu'est-ce qu'un avertissement" non vérifié "?" - ça vaut la peine d'être lu.
(YourClazz<?>)
- Java ne vous avertit jamais de ces transtypages car ils sont sûrs. Cela ne fonctionnera pas toujours cependant (voir la FAQ sur les génériques pour plus de détails).
Il s'agit d'une annotation pour supprimer les avertissements de compilation concernant les opérations génériques non contrôlées (pas les exceptions), telles que les transtypages. Cela implique essentiellement que le programmeur ne souhaitait pas être informé de ceux-ci dont il est déjà conscient lors de la compilation d'un bit de code particulier.
Vous pouvez en savoir plus sur cette annotation spécifique ici:
En outre, Oracle fournit ici une documentation didactique sur l'utilisation des annotations:
Comme ils le disent,
"L'avertissement" non contrôlé "peut se produire lors de l'interfaçage avec du code hérité écrit avant l'avènement des génériques (discuté dans la leçon intitulée Génériques)."
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 / hacks JSR pour résoudre ce problème: jetons de type, jetons de Super Type , Class.cast ().
Si vous avez vraiment besoin de cette suppression, limitez-la autant que 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;
}
L' annotation SuppressWarning est utilisée pour supprimer les avertissements du compilateur pour l'élément annoté. Plus précisément, la unchecked
catégorie permet la suppression des avertissements du compilateur générés à la suite de transtypages de type non contrôlés.
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'avais pas annoté le @SuppressWarnings ("décoché") ici, il y aurait un problème avec la ligne, où je veux retourner ma ResultList.
En raccourci, la sécurité de type signifie: Un programme est considéré comme sûr de type s'il se compile sans erreurs ni avertissements et ne déclenche aucune exception ClassCastException lors de l'exécution.
Je m'appuie sur http://www.angelikalanger.com/GenericsFAQ/FAQSections/Fundamentals.html
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);
Ce qui après l'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 ç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, donc cela compile et s'exécute, comme pour Java Virtual Machine, c'est un transtypage en List
type (c'est la seule chose qu'il peut vérifier, donc il ne vérifie que cela).
Mais maintenant, ajoutez cette ligne.
Integer hello = actualList.get(0);
Et JVM lancera un événement inattendu ClassCastException
, car le compilateur Java a inséré une distribution implicite.
java.lang.ClassCastException: java.base/java.lang.String cannot be cast to java.base/java.lang.Integer
Un unchecked
avertissement 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 pense que le code est sûr et ne provoquera pas d'exceptions inattendues.
Pourquoi voudriez-vous faire ça? 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'une distribution est sûre, mais Java ne fournit pas de moyen de le dire - pour masquer des avertissements comme celui-ci, @SupressWarnings("unchecked")
peut être utilisé, afin qu'un programmeur puisse se concentrer sur de vrais avertissements. Par exemple, Optional.empty()
retourne un singleton pour éviter l'allocation d'options optionnelles 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ûre, car la valeur stockée dans une option vide ne peut pas être récupérée, il n'y a donc aucun risque d'exceptions de conversion de classe inattendues.
Vous pouvez supprimer les avertissements du compilateur et indiquer 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;
}
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 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;
Pour autant que je sache, pour l'instant, il s'agit 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 JDK antérieures à JDK 5, donc tout mélange des anciennes constructions avec les nouvelles peut entraîner des résultats inattendus.
Le compilateur en avertit le programmeur, mais si le programmeur le sait déjà, il peut désactiver ces avertissements redoutés à l'aide de SuppressWarnings.
Un avertissement par lequel le compilateur indique qu'il ne peut pas garantir la sécurité du type. Le terme d'avertissement "non contrôlé" est trompeur. Cela ne signifie pas que l'avertissement est décochée en aucune façon. Le terme «non vérifié» fait référence au fait que le compilateur et le système d'exécution ne disposent pas de suffisamment d'informations sur le type pour effectuer toutes les vérifications de type qui seraient nécessaires pour garantir la sécurité du type. En ce sens, certaines opérations sont "non contrôlées".
La source la plus courante d'avertissements "non vérifiés" est l'utilisation de types bruts. des avertissements "non vérifiés" sont émis lorsqu'un objet est accessible 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 contrôlé en conjonction 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 invoquée, le compilateur ne sait pas s'il est sûr d'ajouter un objet String à la collection. Si le TreeSet est une collection qui contient des String (ou un super-type de celle-ci), alors ce serait sûr. 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 vérifié" est émis.
Des avertissements "non vérifiés" sont également signalés lorsque le compilateur trouve un transtypage dont le type cible est soit un type paramétré soit un paramètre de type.
Exemple (d'un avertissement non contrôlé en conjonction avec un transtypage en un type ou une variable de type paramétré):
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 cast dont le type 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 l'effacement de type est disponible, pas le type statique exact qui est visible dans le code source. Par conséquent, la partie d'exécution de la conversion est effectuée en fonction de l'effacement du type et non du type statique exact.
Dans l'exemple, le transtypage vers Wrapper vérifierait si l'objet renvoyé par super.clone est un wrapper, et non s'il s'agit d'un wrapper avec un type particulier de membres. De même, les transtypages vers le paramètre de type T sont convertis en type Object au moment de l'exécution, et probablement entièrement optimisés. En raison de l'effacement de type, le système d'exécution n'est pas en mesure d'effectuer des vérifications de type plus utiles lors de l'exécution.
D'une certaine manière, le code source est trompeur, car il suggère qu'une conversion vers le type cible respectif est effectuée, alors qu'en fait, la partie dynamique de la conversion ne vérifie que l'effacement du type du type cible. L'avertissement "non vérifié" est émis pour attirer l'attention du programmeur sur cette incompatibilité entre l'aspect statique et dynamique de la distribution.
Veuillez vous référer à: Qu'est-ce qu'un avertissement "non vérifié"?
L'annotation @SuppressWarnings est l'une des trois annotations intégrées disponibles dans JDK et ajoutées aux côtés de @Override et @Deprecated dans Java 1.5.
@SuppressWarnings demande 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 ("non vérifiée") et @SuppressWarnings ("série"), deux des exemples les plus populaires d'annotation @SuppressWarnings. Former est utilisé pour supprimer l'avertissement généré en raison d'une conversion non contrôlée, tandis que l'avertissement ultérieur est utilisé pour rappeler 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