Java泛型问题(带有Spring)

时间:2010-06-03 10:47:23

标签: java generics spring

我想我可能是类型擦除的受害者,但我想先在这里与其他人核对。

我要求做这样的事情:

public interface FooFactory {
   public <T extends Bar> Foo<T> createFoo( Class<T> clazz );
}

编写此代码完全有效。但是,我正在尝试使用Spring BeanFactory来实现此功能,但我无法做到。

我想做的是......

public class FooFactoryImpl implements BeanFactoryAware {
   private BeanFactory beanFactory;

   public <T extends Bar> Foo<T> createFoo( Class<T> clazz ) {
      return beanFactory.getBean( ????????? );
   }

   public void setBeanFactory( BeanFactory beanFactory ) {
      this.beanFactory = beanFactory; 
   }
}

正如你所看到的,我已经投入了????????我想要检索Foo<T>类型的bean,其中T扩展Bar。但是,不可能派生类型为Foo<T>的Class对象,所以我假设我想做的事情是不可能的?

其他人看到了解决这个问题的方法,或者实现我正在尝试做的其他方式吗?

谢谢,

安德鲁

2 个答案:

答案 0 :(得分:3)

是的,这是一种类型擦除情况。由于Class无法获得Foo<T>,因此您必须使用Foo并禁止警告。

@SuppressWarnings("unchecked")
public <T extends Bar> Foo<T> createFoo( Class<T> clazz ) {
      return (Foo<T>) beanFactory.getBean("Name of Bean", Foo.class);
}

您可能会发现this file很有趣 - 这是一个实用工具类,其中包含Apache CXF用于集中所有这些不幸事件的警告。

当然,所有这些都假定您的XML(或其他)配置将导致可用的Foo

答案 1 :(得分:1)

由于您无法在Spring上下文中使用专门的Foo<T>定义类型T的bean,我猜您实际上有Foo<T>的子类:

abstract public class Foo<T> { ... }

public class FooString extends Foo<String> { ... }
public class FooInteger extends Foo<String> { ... }

-

<bean id = "fooInteger" class = "FooInteger" />
<bean id = "fooString" class = "FooString" />

在这种情况下,您可以使用类型参数不会从超类定义中删除的事实:

public class FooFactory implements ApplicationContextAware {

    private Map<Class<?>, Foo<?>> beans = new HashMap<Class<?>, Foo<?>>();

    @SuppressWarnings("unchecked")
    public <T> Foo<T> createFoo(Class<T> c) {
        return (Foo<T>) beans.get(c);
    }

    @SuppressWarnings("unchecked")
    public void setApplicationContext(ApplicationContext ctx)
            throws BeansException {

        Collection<Foo> candidates = ctx.getBeansOfType(Foo.class).values();
        for (Foo candidate: candidates) {
            Type superclass = candidate.getClass().getGenericSuperclass();
            if (superclass instanceof ParameterizedType) {
                ParameterizedType t = (ParameterizedType) superclass;
                Class<?> p = (Class<?>) t.getActualTypeArguments()[0];
                beans.put(p, candidate);
            }
        }
    }
}