2009-01-16 14 views
8

j'ai une classe héritage que la classe elle-même est pas un générique, mais une de ses méthodes retour type utilise génériques:référence non générique aux résultats de classe génériques dans les types de retour non génériques

public class Thing { 
    public Collection<String> getStuff() { ... } 
} 

getStuff() utilise génériques renvoyer une collection de chaînes. Par conséquent, je peux itérer sur getStuff() et il n'y a pas besoin de jeter les éléments à un String:

Thing t = new Thing(); 
for (String s: t.getStuff()) // valid 
{ ... } 

Cependant, si je change Thing lui-même être un tout générique mais gardez bien le même:

public class Thing<T> { 
    public Collection<String> getStuff() { ... } 
} 

puis continuez à utiliser la référence non générique à Thing, getStuff() ne renvoie plus Collection<String> et renvoie à la place un Collection non typé. Ainsi, le code client ne compile pas:

Pourquoi est-ce? Quelles sont les solutions de contournement? Je suppose que, en utilisant une référence non générique à une classe générique, Java désactive tous les génériques pour la classe entière. C'est douloureux, parce que maintenant j'ai brisé mon code client en faisant de Thing un générique.

Editer: Je fais Thing générique pour une autre méthode qui n'est pas répertoriée dans l'exemple de code ci-dessus. Ma question est éducative quant à pourquoi ce qui précède ne peut être fait.

Répondre

10

Ok, prenez deux, j'ai mal compris votre question.

Lorsque vous delcare Thing (on appelle cela un de type cru) au lieu de Thing<?> (Type paramétrés) le compilateur Java bandes sur tous les arguments génériques, même thogh (comme dans votre cas) le type générique de la méthode n'a rien à voir avec le type générique de la classe.

Du (excellent) Java Generics FAQ:

Can I use a raw type like any other type?

Méthodes ou constructeurs d'un type brut ont la signature qu'ils auraient après l'effacement de type.

Cette phrase apparemment inoffensive et discrète décrit le comportement en question. Vous utilisez Thing en tant que type brut, le type de retour est Collection (et non Collection<String>) car il s'agit du type après effacement du type.

Confus? Pas étonnant. Regardez simplement la taille de cette FAQ. Il y a probablement environ trois personnes sur terre qui comprennent toutes les implications de Java Generics. Considérez juste ma déclaration préférée du JDK:

Enum<T extends Enum<T>> 

(Theres une explication de cela dans la FAQ aussi).

+0

Je fais chose générique à cause d'une autre méthode (ne figure pas dans mon exemple). –

+0

Si quelque chose est Chose (et pas Chose ), il ne compilera pas. Allez-y et essayez-le. –

+0

Mal compris la question, changé. – cletus

0

Il échoue en raison de l'effacement.Vous pouvez lire plus à ce sujet dans ces Java Tutorials

0

Je pense que c'est tout à fait normal. À mon avis, en utilisant Thing t = new Thing(); pour la classe générique activée est totalement une erreur. Lorsque le compilateur voit une classe générique utilisée comme une classe sans paramètre de type, il pense qu'il doit effacer tous les types génériques de cette classe. C'est ainsi que vous pouvez compiler d'anciens codes sans utiliser de génériques dans les nouveaux compilateurs java et que le compilateur laisse ces anciens codes utiliser des classes génériques activées (par exemple java.util.ArrayList) sans aucun problème. (et c'est ainsi que java n'a pas besoin de séparer System.Collection.Generic.List et System.Collection.List comme C#). Vous pouvez exécuter Thing t = new Thing(); en ajoutant un paramètre de type simple sur celui-ci, Thing<Object> t = new Thing<Object>();, seule chose dont le compilateur Java a besoin est de s'assurer que vous utilisez java générique consciemment. Je ne peux jamais blâmer Java pour sa grande rétrocompatibilité.

Je sais que je suis un peu en retard: D

Questions connexes