在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();
似乎在重写方法时,没有检查约束。这有点奇怪,因为除非定义了通用类型(例如<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;
}
}
}
答案 0 :(得分:0)
我看到的唯一参数是向后兼容性。例如,如果您正在使用一个返回列表的预先存在的库接口,但是您知道它仅包含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();