Re: Yet another generics question: Needs unchecked conversion to conform to ...
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)
I must use reflection to instantiate the factory. Otherwise, I would
not be posting that question ;)
Why must?
Here is a more complete example that explains in the comments why I am
doing all of this. If you enjoy generics enough to take a look at it
and comment, I'll be more than impressed!
import java.lang.reflect.Constructor;
public class Generics {
/**
* this code will be used in either an OSGi container,
* or in a normal java application.
* So Service implementations are loaded either from
* the OSGi bundle context (when in an OSGi container)
* or from the current class loader using reflection.
* The service finder interface allows to locate the
* Service implementation using a different strategy depending
* on the runtime context.
* Only the reflection strategy is shown here.
* Experimenting with it, I found that I would
* not have to define generices in the interfaces and class
* if I did not have this method:
*
* public void doSomethingWith(T component);
*
* in the Service interface. Wanting to allow a generic type
* as a parameter appears to force me to put generics everywhere.
*/
public static interface ServiceFinder<T extends ServiceComponent> {
public Service<ServiceComponent> find(String id) throws Exception;
}
public static class ServiceFinderUsingReflection
implements ServiceFinder<ServiceComponent> {
public Service<ServiceComponent> find(String serviceId)
throws Exception{
// in real life, the service class name
// is computed differently using
// a pattern or xml config file
String serviceClass = serviceId;
Class<?> bc = Class.forName(serviceClass);
Class<? extends Service> bfc = bc.asSubclass(Service.class);
Constructor<? extends Service> cstr =
bfc.getConstructor(new Class[]{});
Service<?> ret = cstr.newInstance(new Object[]{});
// This is the warning I'd like to get rid of
return (Service<ServiceComponent>)ret;
}
}
public static interface Service<T extends ServiceComponent>{
public T createServiceComponent();
/**
* Using generics here allows implementation class to
* override using their own types.
*/
public void doSomethingWith(T component);
}
public static abstract class ServiceComponent{
}
// ------------------------------------
// Sub-system external implementation
// of Bean and BeanFactory
public static class ServiceComponentX extends ServiceComponent {
public void doIt(){
}
}
public static class ServiceX implements Service<ServiceComponentX>{
/**
* Here, using generics, I can define methods that expect
* a ServiceComponentX.
*/
public void doSomethingWith(ServiceComponentX c) {
c.doIt();
}
public ServiceComponentX createServiceComponent() {
return new ServiceComponentX();
}
}
// ------------------------------------
public static void main(String[] args) throws Exception {
// Use the reflection finder. We may also have chosen to
// use, say, an OSGi-based finder that locates the service
// using the OSGi bundle context.
ServiceFinder<ServiceComponent> finder =
new ServiceFinderUsingReflection();
// Locate the service identified by the service id "ServiceX".
// In this example, it happens to be the class name but in real
// life, it is not the class name, but an ID from which the finder
// implementation uses to locate the real service.
Service<ServiceComponent> service = finder.find("ServiceX");
ServiceComponent component = service.createServiceComponent();
// Setup the component state here
// ...
// once it is setup,
service.doSomethingWith(component);
}
}