我定义了一个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));
}
这就是我想要的,但带有编译器警告。而且我认为我不能在运行时强制转换中表达递归限制。
有没有办法重新编写代码以使其类型安全?
由于
答案 0 :(得分:0)
没有办法将非泛型API转换为泛型而不会收到警告。您可以使用@SuppressWarnings("unchecked")
注释来抑制它
在这种情况下,Class<?>
也毫无意义 - 您可以使用非通用Class candidateClass
代替。
答案 1 :(得分:0)
转换为<? extends Copiable<?>
的运行时失败(在register()
调用中),因为无法声明第一个?
和第二个?
是相同的(未知) )事情。
asSubclass()
调用给出了编译器警告,原因几乎相同 - 因为泛型已被删除,运行时无法证明Copiable
是Copiable<AnythingInParticular>
}。你已经证明它是Copiable
,但你没有证明它是Copiable<Itself>
。
我认为您可以希望的最好的方法是将警告本地化为一种凌乱的方法,并添加@SuppressWarnings("unchecked")
和一些评论。
您确定这会在运行时运行吗?我感觉编译器在这里说实话。您从Hibernate获得的类实际上是扩展Copiable
,还是只是声明了与Copiable
接口匹配的方法?如果是后者,那么 - Java是一种强类型语言 - 无论如何,isAssignableFrom()
始终会返回false。
答案 2 :(得分:0)
也许你可以某种方式应用super type token范式?为什么需要限制你的寄存器()?我认为问题在于你使用的是Class.forName,而且这是一个太多的运行时事件。