将通用值添加到未知类型的通用容器中

时间:2011-07-20 02:05:45

标签: java generics wildcard

有没有办法将动物添加到笼子里? :)

public class Cage<T> extends ArrayList<T> {
    public final String name = "foo";
}

public Zoo {
    List<? extends Cage<?>> zooCages= new ArrayList<Cage<?>>();

    public <T> void addAnimal(String name, T animal){
           for(Cage<?> c : zooCages)
               if(c.name.equals(name)){
                  c.add(animal);       //compile error
                  return;
               }
     }
}
编辑:错别字。 编辑2:完成示例

2 个答案:

答案 0 :(得分:2)

(我假设Cage是一个集合。)

这里有一个概念错误。

c在foreach循环中声明为Cage<?>,即接受未指定类型的笼子。您正尝试向其中添加T类型的对象,但没有理由相信c可以包含T类型的对象。

有关通配符*的含义的详细信息,请参阅http://download.oracle.com/javase/tutorial/java/generics/wildcards.html

您可能希望类中的所有笼子都包含相同(任意)类型T。在这种情况下,整个封闭类应该采用类型参数。例如:

import java.util.*;

public class Main<T> {
    private class Cage extends ArrayList<T> {
        public final String name = "foo";
    }

    List<? extends Cage> zooCages = new ArrayList<Cage>();

    public void addAnimal(String name, T animal) {
        for(Cage c : zooCages) {
             if(c.name.equals(name)) {
                 c.add(animal);
                 return;
             }
        }
    }
}

答案 1 :(得分:1)

您的问题在于使用无界通配符。请参阅以下示例:

Cage<?> cage1 = new Cage<Integer>();
Cage<?> cage2 = new Cage<String>();
Cage<?> cage3 = new Cage<T>();

someMethod(cage1);
someMethod(cage2);
someMethod(cage3);

public void someMethod(Cage<?> cage) {
  cage.add(1);                // Will not compile
  cage.add("A String");       // Will not compile
  cage.add(someValueOfTypeT); // Will not compile
}

从技术上讲,该方法并非严格必要,但您可以轻松查看此代码的问题。 Cage<?>可以是Cage<String>Cage<Anything>。您无法添加任何内容,因为它可能是任何特定的Cage。

如果您要将T添加到Cage,则必须是Cage<T>Cage<? super T>。一种方法是:

public class Zoo<T> {
  private List<? extends Cage<? super T>> cages = new ArrayList<>();

  public void addAnimal(String cageName, T animal) {
    for(Cage<? super T> cage : cages) {
      // Now you can add animal to a cage
    }
  }
}