简体   繁体   中英

Java - Collection of generic classes, each with a different generic type

Suppose you have the following:

@AllArgsConstructor
public class Foo<A> {
  A a;
}

and you have the following:

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

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

And I want to loop over the list of foos

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

First of all, is there a different way of accomplishing this?

Then, how do I reference the generic type of each foo object inside the list? I tried with a wildcard but I'm encountering a compilation error "capture#1-of-? ..."

The following works because in your case you know that the foo types can only be either Integer or String and these are final classes assuming that Foo.a is never ```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");
   }
} 

However in general this won't work if allFoos could be populated with arbitrary Foo types (not know in compilation-time) ... once you mix them all in the same bag/list you loose the ability to figure them out the type that was use in the instantiation code. You could assume that this is the same as the non-null Foo.a member instance but that is not necessarily the case:

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

You would perhaps end up saying that both are Foo<Double> but one was Foo<Number> when was constructed. In this case because Foo is very simple class it might not make a difference but if it had more complex operations perhaps it would.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM