Java - 泛型类的集合,每个类具有不同的泛型类型

时间:2017-06-22 16:44:14

标签: java generics

假设您有以下内容:

@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对象的泛型类型?我尝试使用通配符,但我遇到编译错误“捕获#1-of-?...”

1 个答案:

答案 0 :(得分:0)

以下是有效的,因为在您的情况下,您知道foo类型只能是Integer或String,并且这些是最终类,假设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类型(在编译时不知道),那么这项工作将无法工作......一旦你将它们全部混合在同一个包/列表中,你就会松散能够找出实例化代码中使用的类型。您可以假设这与非null 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>,但one在构建时为Foo<Number>。在这种情况下,因为Foo是一个非常简单的类,它可能没有什么区别,但如果它有更复杂的操作,也许它会。