2009-05-27 6 views
36

J'ai une question Java sur les génériques. Je déclarais une liste générique:Liste <? extends MyType>

List<? extends MyType> listOfMyType; 

Puis, dans une méthode que j'essaie instancier et ajouter des éléments à cette liste:

listOfMyType = new ArrayList<MyType>(); 
listOfMyType.add(myTypeInstance); 

myTypeInstance est juste un objet de type MyType; il ne compilera pas. Il dit:

La méthode add (? Capture # 3 de étend MyType) dans le type Liste < capture # 3 de ? extends MyType> n'est pas applicable pour les arguments (MyType)

Une idée?

Répondre

29

Vous ne pouvez pas faire un "put" avec étend. Regardez Generics - Get and Put rule.

+9

Comme le dit Josh Bloch: "Souviens-toi PECS: Producteur Prolonge, la consommation super." Comme listOfMyType est un consommateur (que vous ajoutez), 'super' est valide et' extends' ne l'est pas. –

+0

Les liens sont maintenant rompus. –

+0

Point de pedantry: Vous pouvez 'mettre'' null' avec "extends".Vous pouvez également capturer le type et "mettre" les références que vous avez "obtenu". –

4

Vous ne devriez pas avoir besoin d'utiliser la syntaxe de capture générique dans votre cas, déclarant simplement

List<MyType> listOfMytype; 

devrait être suffisant. Si vous voulez savoir exactement pourquoi, le Java Generics Tutorial a plus que vous ne voudriez savoir sur la folie ésotérique de Java Generics. La page 20 traite de votre cas particulier. Quant à savoir pourquoi ajouter avec la capture générique ne fonctionne pas, c'est parce que le compilateur ne peut pas déterminer exactement quelle sous-classe de MyType la liste sera dans tous les cas, donc le compilateur émet une erreur.

22

Tenir compte:

class MySubType extends MyType { 
} 

List<MySubType> subtypeList = new ArrayList<MySubType>(); 
List<? extends MyType> list = subtypeList; 
list.add(new MyType()); 
MySubType sub = subtypeList.get(0); 

sub contient maintenant un MyType qui est très mauvais.

+0

Ne devrait pas le "list.get (0);" en fait être "subtypeList.get (0);" ? – Zds

+0

@Zds Yup, corrigé. Merci. –

2

Il y a un fil similaire ici: How can elements be added to a wildcard generic collection?

Pour avoir une idée de la façon dont les génériques œuvres vérifier cet exemple:

List<SubFoo> sfoo = new ArrayList<SubFoo>(); 
    List<Foo> foo; 
    List<? extends Foo> tmp; 

    tmp = sfoo; 
    foo = (List<Foo>) tmp; 

La chose est, qui n'a pas été conçu pour membre local/variables, mais pour les signatures de fonction, c'est pourquoi il est si ass-backward.

2

Je ne sais pas si cela va vraiment vous aider, mais cela est quelque chose que je devais utiliser tout en appelant une méthode générique de Spring Framework et de vouloir retourner une liste générique:

public <T> List<T> findAll(String tableName,Class<?> table) { 
    String sql = "SELECT * FROM "+ tableName ; 
    List<?> entities = getSimpleJdbcTemplate().query(sql, 
      ParameterizedBeanPropertyRowMapper.newInstance(table)); 
      return (List<T>) entities; 
} 

Semble les besoins de paramétrisation vous d'utiliser le? connectez-vous à la liste pour recevoir les résultats, puis copiez la liste dans le type de retour attendu.

Iam encore ébloui par les génériques ...

Questions connexes