包装工厂方法的通用类型

时间:2013-06-30 11:08:05

标签: java generics

我正在尝试为包装器创建一个工厂方法,而且我对这些泛型类型感到磕磕绊。

我有两个A和B类,其中B派生自A.然后我有一个Wrappber基类(WBase)和 包装类WA和WB用于A和B.

编译下面的代码时,我得到了一个

  

类型安全:未检查的调用类型的通用方法包装(Class,T)的调用包(Class,Test.B)

关于调用wrap方法的

警告?任何想法如何做对吗?

干杯

public class Test {

    public class A {
    }

    public class B extends A {
    }

    public class WBase<T> {
    }

    public class WA<T extends A> extends WBase<T> {
    }

    public class WB extends WA<B> {
    }

    public <T, W extends WBase<T>> W wrap(Class<W> cls, T item) {
        return null;
    }

    public void test() {
        B b = new B();
        wrap(WA.class, b);
    }
}

更新

我刚刚解决了我的问题! :-)我找到的解决方案是引入一个额外的包装类WABase,让WA从该类扩展,并从WA中删除泛型参数:

public class WABase<T extends A> extends WBase<T> {} 
public class WA extends WBase<A> {} 
public class WB extends WABase<B> {} 

此外,我将wrap方法重新定义为

<T, W extends WBase<? super T>> W wrap(Class<W> cls, T item) 

现在一切正常:

B b = new B(); 
A a = new A(); 
wrap(WB.class, b); 
// wrap(WB.class, a); // does not compile, which is right 
wrap(WA.class, a); 
wrap(WA.class, b);

感谢morgano和newacct推动我走向正确的方向。

3 个答案:

答案 0 :(得分:2)

您可以按照自己的意愿来展示WA.classClass<WA>而不是Class<WA<B>>的事实:

wrap((Class<WA<B>>)(Class<?>)WA.class, b);

当然,你会得到未经检查的施法警告。

答案 1 :(得分:1)

问题在于这一部分:

wrap(WA.class, b)

WA是一个参数化类,当您使用 WA.class 时,您使用的是“原始”类型。

答案 2 :(得分:0)

由于b的类型为B,因此wrap(WA.class, b)调用T中的BT。 由于BClass,因此作为第一个参数传递的WBase<B>实例的类型变量必须扩展WA.classWA的类型变量为WBase<T>,显然确实扩展了T

public class WA<T extends A> extends WBase<T> 中的T不是public <T, W extends WBase<T>> W wrap(Class<W> cls, T item) 中的T。这是两个独立的独立T。如果您使用S切换其中一个{{1}},您会看到它仍然可以编译。