java - 为什么在实现(覆盖)具有此类约束的方法时,Java 允许忽略/删除通用约束?
问题描述
在实现(覆盖)具有此类约束的方法时,它允许忽略/删除通用约束是 Java 中的一个限制吗?
或者,它是否按预期工作,这是滥用的一个例子,而不是预期会导致问题的问题?
我可以编写一个具有通用约束的接口:
public interface X
{
public <T extends Number> List<T> get();
}
然后我可以在忽略约束的接口中实现这样的:
public static class BadX implements X
{
@Override
public List<String> get()
{
return Arrays.asList("a", "b", "c");
}
}
现在,当使用这样的实现时,我可以分配一个错误的类型,而不会出现任何编译时或运行时错误:
X x = new BadX();
// wooops, it's actually a list of strings,
// but no compile-time nor runtime errors
List<Double> doubles = x.get();
似乎在覆盖该方法时,未检查约束。这有点奇怪,因为 List 返回类型是不允许的,除非定义了泛型类型(例如<T>
,或<T extends OtherType>
)。
下面的完整代码示例:
import java.util.Arrays;
import java.util.List;
public class JavaFiddle
{
public static void main(String[] args)
{
System.out.println("STARTED");
NumberSource ns = new IntegerSource(Arrays.asList(1, 2, 3));
// wooops, it's actually a list of integers,
// but no compile-time nor runtime errors
List<Double> doubles = ns.getSource();
// works
printNumbers(doubles);
// runtime error
printDoubles(doubles);
System.out.println("DONE");
}
public static void printNumbers(List<? extends Number> numbers)
{
for (Number n : numbers)
System.out.println(n);
}
public static void printDoubles(List<Double> doubles)
{
for (Double d : doubles)
System.out.println(d);
}
public interface NumberSource
{
public <T extends Number> List<T> getSource();
}
public static class IntegerSource implements NumberSource
{
private List<Integer> source;
public IntegerSource(List<Integer> integers)
{
this.source = integers;
}
@Override
public List<Integer> getSource()
{
return source;
}
}
}
解决方案
我看到的唯一论点是向后兼容性。例如,如果您正在使用返回 List 的预先存在的库接口,但您知道它只包含 Integer 对象,则可以强制转换它:
List<Integer> myList = legacyObject.legacyGetList(); // returns a List
请参阅本文档的第 6.1 节: https ://www.oracle.com/technetwork/java/javase/generics-tutorial-159168.pdf
您可能已经在考虑这一点,但在您的情况下,将 NumberSource 实现为泛型类并使用类似的东西可能更安全/更易于维护
NumberSource<Integer>
IntegerSource 将扩展 NumberSource。这将允许如下代码:
NumberSource<Integer> ns = new IntegerSource(Arrays.asList(1, 2, 3));
// This no longer compiles
List<Double> doubles = ns.getSource();
推荐阅读
- javascript - ReactJS:如何传递字符串以用作函数名?
- android - 如何重新生成 android_gradle_build.json 以使我的 NDK 项目从 Gradle 构建?
- mongodb - 可以在 Mongo 中有效索引的列表的最佳方法
- python - pytorch nn.L1Loss 与 Sklearn 的 l1 损失 - 优化结果非常不同?
- javascript - 如何使用 socket.io 在与多个用户的会话中保留变量?
- android - android 应用程序中的泄漏:SmoothScroller 的一个实例被启动了不止一次
- c++ - Windows 后台服务(系统配置文件)无法使用 C++ 访问 win 10 上的用户 appData 文件夹?
- timestamp - 查找包含异常值的两个数据集之间的偏移量
- python - np.roll 不翻边
- python - 保存/加载带有模式的匹配器作为新的管道组件