假设您有以下内容:
@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-?...”
答案 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
是一个非常简单的类,它可能没有什么区别,但如果它有更复杂的操作,也许它会。