Re: Yet another generics question: Needs unchecked conversion to
conform to ...
Michel T. wrote:
Rather strangely it requires an intermediate variable. I have no idea
why. Captures are odd.
I tried and you are right, it got rid of the warning. But doing so, I
had changed the signature of the method that broke the client code
elsewhere. So I am back to the original version of the method that has
this signature:
BeanFactory<Bean> createFactory2(Strig name)
You have not and in general cannot verify that the object is of that
type. The signature is wrong. For instance, in your example ServiceX is
not a Service<ServiceComponent> but it is a Service<? extends
ServiceComponent>.
Generally a good move when using reflection and generics, is to add a
layer of indirection, so you don't have to mix the two.
So instead of loading Service<? extends ServiceComponent>, load a
ServiceProvider:
interface ServiceProvider {
<T extends ServiceComponent> Service<T> find(
Class<T> componentClass
);
}
class ServiceProviderX implements ServiceProvider {
@SuppressWarnings("unchecked")
<T extends ServiceComponent> Service<T> find(
Class<T> componentClass
) {
if (componentClass != ServiceComponentX.class) {
throw new SomeException();
}
return (Service<T>)new ServiceX();
}
}
I think you are stuck with the unchecked warning there, but at least the
code is now sound. Alternatively, add an asSubclass-like method to Service.
Really, we want a Service interface for each type of ServiceComponent. So:
public interface ServiceComponent {
}
public interface Service<T extends ServiceComponent> {
T createServiceComponent();
void doSomethingWith(T component);
}
public interface XServiceComponent implements ServiceComponent {
}
public interface XService extends Service<XServiceComponent> {
}
class XServiceComponentImpl implements XServiceComponent {
}
public class XServiceImpl implements XService {
public XServiceComponent createServiceComponent() {
return new XServiceComponentImpl();
}
public void doSomethingWith(XServiceComponent component) {
...
}
}
....
public <T extends Service<?>> find(
Class<T> clazz, String serviceClassName
) throws
NullPointerException,
LinkageError,
ExceptionInInitializerError,
ClassNotFoundException,
ClassCastException,
NoSuchMethodException,
SecurityException,
InstantiationException,
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
{
...
return clazz.cast(service);
}
....
// Or: ServiceX service = find(
Service<XServiceComponent> service = find(
XService.class, className
);
Tom Hawtin