转换为递归有界类型

时间:2009-07-14 16:47:37

标签: java generics casting

我定义了一个Java接口来表示对象复制自身的能力(不,我不想使用Cloneable,但感谢您的建议;-)。这是通用的:

public interface Copiable<T> {
    T copy();
}

对象只会复制自己的类型:

public class Foo implements Copiable<Foo> {
    Foo copy() { return new Foo(); }
}

现在,我正在从非通用API中读取Class<?>个对象(Hibernate元数据,如果这是任何人都感兴趣的话),如果它们是Copiable,我想注册它们我的一个组件。 register方法具有以下签名:

<T extends Copiable<T>> register(Class<T> clazz);

我的问题是,如何在将类传递给方法之前将其强制转换?我目前正在做的是:

Class<?> candidateClass = ...
if (Copiable.class.isAssignableFrom(candidateClass)) {
    register(candidateClass.asSubclass(Copiable.class));
}

这就是我想要的,但带有编译器警告。而且我认为我不能在运行时强制转换中表达递归限制。

有没有办法重新编写代码以使其类型安全?

由于

3 个答案:

答案 0 :(得分:0)

没有办法将非泛型API转换为泛型而不会收到警告。您可以使用@SuppressWarnings("unchecked")注释来抑制它 在这种情况下,Class<?>也毫无意义 - 您可以使用非通用Class candidateClass代替。

答案 1 :(得分:0)

转换为<? extends Copiable<?>的运行时失败(在register()调用中),因为无法声明第一个?和第二个?是相同的(未知) )事情。

asSubclass()调用给出了编译器警告,原因几乎相同 - 因为泛型已被删除,运行时无法证明CopiableCopiable<AnythingInParticular> }。你已经证明它是Copiable,但你没有证明它是Copiable<Itself>

我认为您可以希望的最好的方法是将警告本地化为一种凌乱的方法,并添加@SuppressWarnings("unchecked")和一些评论。

您确定这会在运行时运行吗?我感觉编译器在这里说实话。您从Hibernate获得的类实际上是扩展Copiable,还是只是声明了与Copiable接口匹配的方法?如果是后者,那么 - Java是一种强类型语言 - 无论如何,isAssignableFrom()始终会返回false。

答案 2 :(得分:0)

也许你可以某种方式应用super type token范式?为什么需要限制你的寄存器()?我认为问题在于你使用的是Class.forName,而且这是一个太多的运行时事件。