2008-10-27 2 views
14

J'étends une classe définie dans une bibliothèque que je ne peux pas changer:Des avertissements non contrôlés peuvent-ils être évités lors du remplacement d'une méthode avec des paramètres de type brut?

public class Parent 
{ 
    public void init(Map properties) { ... } 
} 

Si je suis en train de définir une classe « enfant » qui étend Parent et j'utilise Java 6 avec les génériques, ce qui est la meilleure façon de remplacer la méthode init sans obtenir des avertissements non vérifiés?

public class Child extends Parent 
{ 
    // warning: Map is a raw type. References to generic type Map<K,V> should be parameterized 
    public void init(Map properties) { } 
} 

Si j'ajouter des paramètres génériques, je reçois:

// error: The method init(Map<Object,Object>) of type Child has the same erasure as init(Map) of type Parent but does not override it 
    public void init(Map<Object,Object>) { ... } 
    // same error 
    public void init(Map<? extends Object,? extends Object>) { ... } 
    // same error 
    public void init(Map<?,?>) { ... } 

Cette erreur se produit indépendamment du fait que j'utilise un type particulier, un caractère générique borné, ou un caractère générique sans bornes. Existe-t-il un moyen correct ou idiomatique de remplacer une méthode non générique sans avertissement, et sans utiliser @SuppressWarnings ("non coché")?

Répondre

12

Oui, vous devez déclarer la méthode dérogatoire avec la même signature que dans la classe parente, sans ajouter d'info génériques.

Je pense que votre meilleur pari est de ajoutez l'annotation @SuppressWarnings("unchecked") au paramètre de type brut, et non à la méthode, de sorte que vous ne supprimiez pas les autres avertissements génériques que vous pourriez avoir dans votre propre code

+0

@SuppressWarnings est certainement votre meilleur pari ici. Suce, mais c'est ce qui arrive quand vous essayez de forcer des génériques dans une bibliothèque qui ne les utilise pas. –

+0

'@SuppressWarnings (" rawtypes ")' devrait également suffire. –

2

Réponse courte: aucun moyen de le faire.

Réponse insatisfaisante: désactivez les avertissements (spécifiques) dans votre IDE/build.xml.

Si vous ne pouvez pas changer la bibliothèque, hélas, vous devez vous contenter de méthodes non génériques. Le problème est que, même après l'effacement du type, les deux init() ont la même signature, ils peuvent en fait être des méthodes différentes - ou les mêmes (*). Le compilateur ne peut pas dire s'il doit surcharger ou surcharger, c'est donc interdit. Supposons que le développeur de bibliothèque comprenne init (Map < String, Integer >). Maintenant vous implémentez init (Map < String, String >). Ceci est surchargé, et deux méthodes devraient exister dans la classe vtable of Child.

Mais que se passe-t-il si le développeur de bibliothèque signifie init (Map < String, String >)? Ensuite, il surcharge, et votre méthode devrait remplacer init init dans la classe enfant, et il n'y aurait qu'une seule méthode dans la vtable de Child.

P.S. Je déteste la façon dont Generics implémenté en Java :-(

+0

Pouvez-vous expliquer pourquoi les méthodes avec la même signature (effacée) peuvent être des méthodes différentes pour le compilateur? Le compilateur ne sait pas ce que le développeur _meant_ lors du codage ... ;-) – nrainer

0

Vous devez déclarer la méthode avec la même signature que le parent, Vous pouvez donc les supprimer avec @SuppressWarnings ("non coché")

La raison pour laquelle il n'y a aucun moyen de se débarrasser de cela est que les avertissements sont là pour vous faire savoir qu'il est possible de créer des collections avec des types invalides en eux. Les avertissements devraient disparaître seulement quand tout le code qui pourrait permettre cela a été enlevé. Puisque vous héritez d'une classe non générique, il sera toujours possible de créer une collection avec un contenu invalide.

2

Je pense que la réponse ci-dessus signifiait dire @SuppressWarnings ("rawtypes") à la place.

Questions connexes