2017-06-22 89 views
0

假設你有以下:爪哇 - 收集泛型類的,每一個不同的泛型類型

@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-?...」

+0

「那麼,我該如何引用列表中每個foo對象的泛型」< - 爲什麼要這樣做呢?你的目標是什麼?至於另一種實現這種方式的方法:既然你的Foo類沒有太多的功能,我不明白你爲什麼不使用列表。 –

+0

當您單獨使用'Foo'時,您使用的是* raw * generic。不要這樣做。爲了使列表中包含'Foo '和'Foo ',將其聲明爲'List >'。然後循環應該是'for(Foo foo:foos)',並且在構建混合列表時,你現在每個人都有正常的問題:你不知道每個值調用'instanceof'的類型。因此,您需要在循環內部使用像if(foo.getA()instanceof String){...}這樣的代碼,這通常是一個壞主意。 – Andreas

回答

0

下面的工作原理是因爲在你的情況下,你知道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.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是非常簡單的類,它可能沒有區別,但如果它有更復雜的操作,也許它會。