将泛型值添加到未知类型的泛型容器

发布于 2024-11-25 01:25:29 字数 556 浏览 1 评论 0原文

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

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:完成示例

is there a way to add the animal to the cage? :)

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;
               }
     }
}

EDIT: Typos.
EDIT 2 : complete the example

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

娇柔作态 2024-12-02 01:25:29

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

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 可以是 CageCage。您无法向其中添加任何内容,因为它可以是任何特定的 Cage。

如果您想将 T 添加到 Cage,它必须是 Cage 还是 Cage<?超级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
    }
  }
}

Your problem is with the use of unbounded wildcards. See the following example:

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
}

Technically, the method wasn't strictly necessary, but you can easily see the problem with this code. A Cage<?> can be a Cage<String> or a Cage<Anything>. You can't add anything to it because it could be any specific Cage.

If you want to add T to a Cage it has to be a Cage<T> or a Cage<? super T>. One way you can do this is:

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
    }
  }
}
治碍 2024-12-02 01:25:29

(我假设 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;
             }
        }
    }
}

(I'm assuming Cage is a collection.)

You have a conceptual error here.

c is declared in the foreach loop as a Cage<?>, i.e. a cage that accepts an unspecified type. You are trying to add an object of type T to it, but there's no reason to believe that c can contain objects of type T.

See http://download.oracle.com/javase/tutorial/java/generics/wildcards.html for details on what the wildcard * means.

You probably wanted all the cages in the class to contain the same (arbitrary) type T. In this case, the entire enclosing class should take a type parameter. For example:

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;
             }
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文