1

我正在尝试为包装器创建一个工厂方法,但我对泛型类型感到困惑。

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

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

类型安全:Test 类型的泛型方法 wrap(Class, T) 的未经检查的调用 wrap(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 将我推向正确的方向。

4

3 回答 3

2

您可以绕过事实,WA.classClass<WA>不是Class<WA<B>>您想要的:

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

当然,您会收到未经检查的强制转换警告。

于 2013-06-30T21:58:54.143 回答
1

问题出在这部分:

wrap(WA.class, b)

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

于 2013-06-30T11:22:10.030 回答
0

既然b是类型B,那么在你的wrap(WA.class, b)调用T中是B。既然TB,那么Class作为第一个参数传递的实例的类型变量必须扩展WBase<B>WA.classis的类型化变量WA显然是 extendWBase<T>

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

于 2013-06-30T11:26:41.870 回答