我正在尝试为包装器创建一个工厂方法,而且我对这些泛型类型感到磕磕绊。
我有两个A和B类,其中B派生自A.然后我有一个Wrappber基类(WBase)和 包装类WA和WB用于A和B.
编译下面的代码时,我得到了一个
关于调用wrap方法的类型安全:未检查的调用类型的通用方法包装(Class,T)的调用包(Class,Test.B)
警告?任何想法如何做对吗?
干杯
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推动我走向正确的方向。
答案 0 :(得分:2)
您可以按照自己的意愿来展示WA.class
为Class<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
中的B
为T
。
由于B
是Class
,因此作为第一个参数传递的WBase<B>
实例的类型变量必须扩展WA.class
。 WA
的类型变量为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}},您会看到它仍然可以编译。