Я хотел бы знать, почему код ☆2
можно скомпилировать с помощью Java8
:
public class Sandbox {
public static void main(String[] args) {
// ☆1: NG: Type mismatch: cannot convert from Object to String
String res0 = IList.nil().head();
// ☆2: OK: I don't know why it OK.
String res1 = IList.nil().head2();
}
static class IList<E> {
static <Z> IList<Z> nil() {
return null;
}
E head() {
return null;
}
<TeE extends E> TeE head2() {
return null;
}
}
}
Примечание. Также мне интересно, что цель JEP (http://openjdk.java.net/jeps/101).
Обычно Java по умолчанию использует generics для своей внешней границы. В этом конкретном случае он
String res1 = IList.<Object>nil().<String>head2();
... потому что только внешний метод вызывает "знает" желаемый тип результата.
Это не имеет ничего общего с Java 8. # 2 также компилируется на Java 7.
Я думаю, что все это сводится к тому, что <TeE extends E>
в вашем методе head2
. Java видит, что вы ожидаете String
в ответ, из-за этой строки:
String res1 = IList.nil().head2();
Поэтому делается вывод, что, ах, в этом случае я буду возвращать String
сейчас - потому что String
расширяет Object
, поэтому <TeE extends E>
является действительным.
Это работает благодаря тому, что вы возвращаете значение null внутри метода. Если вы этого не сделаете, в этом методе возникнет ошибка. И поскольку значение null может быть присвоено всем, кроме примитивов, этот код в порядке.