我有一个包含具有此签名的方法的接口(interface):
<P extends MergeProperty<T> & RestartApplicant> List<P> loadPropertiesFrom(T p1, T p2);
基本上,MergeProperty
是一个不实现 RestartApplicant
的类,而 RestartApplicant
是一个函数接口(interface),其中包含对于理解这个问题来说,这种方法并不重要。
这里有一个问题。当我创建一个实现此接口(interface)的类时,Java 允许我运行以下代码,没有任何编译错误:
public class MyImplementation implements MyInterfacePreviouslyDescribed {
@Override
public List<MergeProperty<MathObject>> loadPropertiesFrom(MathObject p1, MathObject p2) {
return Arrays.asList(
// some random instances of MergeProperty that do not implement RestartApplicant
);
}
}
显然,我不尊重那里的实现限制。有了这个签名,我使用 Arrays.asList(...) 返回的列表不需要需要包含实现 RestartApplicant
的元素。请记住,MergeProperty
不实现 RestartApplicant
。所以这很可能最终会在某个地方导致一些转换错误。
尽管如此,我还是收到了警告:
Type safety: The return type List<Main.MergeProperty<Main.MathObject>> for
loadPropertiesFrom(Main.MathObject, Main.MathObject) (...) needs unchecked
conversion to conform to List<Main.MergeProperty&Main.RestartApplicant> from the
type Main.Test<Main.MathObject>
我的问题是:为什么我只收到警告?在我看来,我不应该能够编译我的代码。有什么特别的原因吗?
提前致谢。
编辑
在对我的代码进行了一些操作之后,我发现如果我将“泛型声明”移至类级别,这将导致:
interface MyInterfacePreviouslyDescribed<T, P extends MergeProperty<T> & RestartApplicant>
而不仅仅是
interface MyInterfacePreviouslyDescribed<T>
显然
List<P> loadPropertiesFrom(T p1, T p2);
而不是
<P extends MergeProperty<T> & RestartApplicant> List<P> loadPropertiesFrom(T p1, T p2);
然后,如果我尝试与以前相同的“非法”实现,我实际上会得到编译错误。看起来更奇怪了......
最佳答案
你甚至可以这样做:
@Override
public List<String> loadPropertiesFrom(MathObject p1, MathObject p2) {
return Arrays.asList(
// some random instances of MergeProperty that do not implement RestartApplicant
);
}
在第一种情况下。这是因为重写的方法不是通用的,并且删除这些方法将是List
。为什么这是允许的?坦白说我不知道,可能与向后兼容性有关。
在你的第二个例子中,看起来它确实应该是:
interface MyInterfacePreviouslyDescribed<T, P extends MergeProperty<T> & RestartApplicant> {
并且在实现中您强制类型正确。实际上,第二个例子是直观的——因为它不能编译;这是预期的。另一方面,第一个依赖于非泛型方法的某些兼容性规则,该规则允许覆盖相同的删除。
关于java - "Illegal"泛型方法的实现 : Why don't I get any compilation error?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58599217/