Java - 含有不同泛型类型的泛型类集合

4
假设您有以下内容:
@AllArgsConstructor
public class Foo<A> {
  A a;
}

并且您拥有以下内容:

Foo<String> fooString = new Foo<>("abc");
Foo<Integer> fooInteger = new Foo<>(10);

List<Foo> foos = new ArrayList<>();
foos.add(fooString);
foos.add(fooInteger);

我希望能循环遍历foos列表。

for (Foo foo : foos) {
    ...
}

首先,有没有实现这个功能的不同方法?

然后,如何引用列表中每个foo对象的通用类型?我尝试使用通配符,但遇到一个编译错误"capture#1-of-? ..."。


那么,我如何在列表中引用每个foo对象的通用类型?你为什么想要这样做?你的目标是什么?至于另一种实现方式:由于您的Foo类并没有真正做太多事情,我不明白为什么您不只使用List<Object>。 - user6073886
当你单独使用 Foo 时,你正在使用一个原始的泛型。不要这样做。为了使列表包含 Foo<String>Foo<Integer>,请将其声明为 List<Foo<?>>。循环应该是 for (Foo<?> foo : foos),现在你有了构建混合列表时普遍存在的正常问题:在调用 instanceof 时你不知道每个值的类型。因此,在循环内部需要像 if (foo.getA() instanceof String) { ... } 这样的代码,这通常是一个坏主意。 - Andreas
1个回答

2
以下代码之所以有效,是因为在您的情况下,您知道 foo 类型只能是 Integer 或 String,而且这些都是 final 类。假设 Foo.a 从不为 ```null```。
Foo<String> stringFoo = ...;
Foo<Integer> integerFoo = ...;

List<Foo<?>> allFoos = new ArrayList<>();
allFoos.add(stringFoo);
allFoos.add(integerFoo);

for (Foo<?> foo : allFoos) {
   if (foo.a instanceof Integer) {
      @SuppressWarnings("unchecked");
      Foo<Integer> intFoo = (Foo<Integer>) foo;
      //...
   } else if (foo.a instanceof String) {
      @SuppressWarnings("unchecked")
      Foo<String> strFoo = (Foo<String>) str;
      //...
   } else {
      throw new IllegalStateException("this cannot happen");
   }
} 

然而,通常情况下,如果allFoos可以填充任意Foo类型(在编译时不知道)...一旦将它们混合放入同一个包/列表中,您就会失去找出用于实例化代码的类型的能力。您可以假设这与非空Foo.a成员实例相同,但这不一定是这种情况:

// assuming constructor defined as Foo(A a) { this.a = a };
Foo<Number> one = new Foo<>((double) 100);
Foo<Double> two = new Foo<>(100);

Foo<?> oneUnknown = one;
Foo<?> twoUnknown = two;

你可能会说两者都是Foo<Double>,但在构造时oneFoo<Number>。在这种情况下,因为Foo类非常简单,所以可能没有什么区别,但如果它有更复杂的操作,那可能会有影响。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接