class ServiceLoader<S> implements Iterable<S> {
// ...
}
interface Foo<T> {
// ...
}
class FooRepository {
void add(Iterable<Foo<?>> foos) {
// ...
}
}
FooRepository repo = new FooRepository();
repo.add(ServiceLoader.load(Foo.class));
This yields a compiler error: "The method add(Iterable<Foo<?>>)
in the type FooRepository is not applicable for the arguments (ServiceLoader<Foo>)
".
I was hoping to be able to treat an Iterable<Foo>
as an Iterable<Foo<?>>
, but on its own it doesn't seem to work. What would be the cleanest way to transmute the result of ServiceLoader.load(Foo.class)
into something I can feed to FooRepository.add()
?
If you're talking about
java.util.ServiceLoader<S>
, then its Javadoc says:Combined with the way that the provider class is clearly instantiated using reflection, that tells me that a provider class declared with a generic type argument will in fact be instantiated as a raw type.
Thus, because you're passing in an object of type
Class<Foo>
-- and there's no way in Java to construct a object of typeClass<Foo<Bar>>
-- then what you get back is what you asked for, anIterable<Foo>
, whereFoo
is the raw type created fromFoo<T>
.Unfortunately, I think the simple answer is: Don't do that then! Either make your provider class be a concrete subclass of the generic type, or else make your provider class be simply a factory that can construct new objects of the appropriate generic type.
Honestly, I can't think of any good reason to make a generic service provider class anyway -- where would you provide the type arguments? I think the factory mechanism is your best bet.