How can I iterate over a wildcard generic? Basically I would like to inline the following method:
private <T extends Fact> void iterateFacts(FactManager<T> factManager) {
for (T fact : factManager) {
factManager.doSomething(fact);
}
}
If this code is in a separate method as shown, it works because the generic method context allows to define a wildcard type (here T
) over which one can iterate. If one tries to inline this method, the method context is gone and one cannot iterate over a wildcard type anymore. Even doing this automatically in Eclipse fails with the following (uncompilable) code:
...
for (FactManager<?> factManager : factManagers) {
...
for ( fact : factManager) {
factManager.doSomething(fact);
}
...
}
...
My question is simply: Is there a way to put some wildcard type one can iterate over, or is this a limitation of generics (meaning it is impossible to do so)?
Best Answer
No. In situation like this, the workaround is to create a helper method.
The JLS has this example http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.10
The issue is, we have a
List<?>
object. We know it must be aList<X>
of someX
, and we'd like to write code usingX
. Internally compiler does convert the wildcard to a type variableX
, but Java language does not offer programmers a direct way to access it. But if there's a method acceptingList<T>
, we can pass the object to the method. Compiler infers thatT=X
and the call is good.If there's no type erasure,
X
can be known at runtime, then Java would definitely give us a way to accessX
. However as of today sinceX
isn't available at runtime, there's not much point. A purely synthetic way could be provided, which is unlikely to be simpler than the helper method workaround.