Для следующего фрагмента кода:
import java.util.List;
public class Main {
interface Interface1<T> {}
interface Interface2<T> extends Interface1<T> {}
static class Bound {}
interface BoundedI1<T extends Bound> extends Interface1<T> {}
interface BoundedI2<T extends Bound> extends Interface2<T> {}
public static void main(String[] args) {
test((List<BoundedI2<?>>) null);
//test2((List<BoundedI2<?>>) null);
}
public static void test(List<? extends Interface2<? extends Bound>> list) { test2(list); }
public static void test2(List<? extends Interface1<? extends Bound>> list) {}
}
Компилятор в порядке с первым вызовом, но жалуется, если я раскомментирую второй. Является ли это ошибкой в системе вывода типов, или кто-нибудь может объяснить, почему здесь действуют правила вывода в JLS?
Протестировано на Oracle JDK 6u43 и 7u45.
UPDATE: Кажется, что eclipsec принимает его просто отлично. К сожалению, я не могу изменить нашу toolchain: P, но интересно найти различия в компиляторах.
Сообщение об ошибке, напечатанное ideone (крутой инструмент btw):
Main.java:12: error: method test2 in class Main cannot be applied to given types;
test2((List<BoundedI2<?>>) null);
^
required: List<? extends Interface1<? extends Bound>>
found: List<BoundedI2<?>>
reason: actual argument List<BoundedI2<?>> cannot be converted to List<? extends Interface1<? extends Bound>> by method invocation conversion
UPDATE 2: Это компилируется отлично, что указывает на то, что компилятор считает, что BoundedI2<?>
можно присваивать Interface1<? extends Bound>
, что, кажется, более прямо противоречит JLS:
public class Main {
interface Interface1<T> {}
interface Interface2<T> extends Interface1<T> {}
static class Bound {}
interface BoundedI1<T extends Bound> extends Interface1<T> {}
interface BoundedI2<T extends Bound> extends Interface2<T> {}
public static void main(String[] args) {
test((List<BoundedI2<?>>) null);
//test2((List<BoundedI2<?>>) null);
test3((BoundedI2<?>) null);
}
public static void test(List<? extends Interface2<? extends Bound>> list) { test2(list); }
public static void test2(List<? extends Interface1<? extends Bound>> list) {}
public static void test3(Interface1<? extends Bound> instance) {}
}