Является ли ограничение в 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;
}
}
}