Це приклад із реального світу з API сторонньої бібліотеки, але спрощений.
Укладено з Oracle JDK 8u72
Розглянемо ці два методи:
<X extends CharSequence> X getCharSequence() {
return (X) "hello";
}
<X extends String> X getString() {
return (X) "hello";
}
Обидва повідомляють про попередження "без перевірки" - я розумію, чому. Що мене бентежить, це те, чому я можу дзвонити
Integer x = getCharSequence();
і вона компілює? Компілятор повинен знати, що Integer
не реалізується CharSequence
. Заклик до
Integer y = getString();
видає помилку (як очікувалося)
incompatible types: inference variable X has incompatible upper bounds java.lang.Integer,java.lang.String
Чи може хтось пояснити, чому б така поведінка вважалася дійсною? Як це було б корисно?
Клієнт не знає, що цей дзвінок небезпечний - код клієнта складається без попередження. Чому компілятор не попередив би про це / не видав помилку?
Також, чим він відрізняється від цього прикладу:
<X extends CharSequence> void doCharSequence(List<X> l) {
}
List<CharSequence> chsL = new ArrayList<>();
doCharSequence(chsL); // compiles
List<Integer> intL = new ArrayList<>();
doCharSequence(intL); // error
Спроба пройти List<Integer>
подає помилку, як очікувалося:
method doCharSequence in class generic.GenericTest cannot be applied to given types; required: java.util.List<X> found: java.util.List<java.lang.Integer> reason: inference variable X has incompatible bounds equality constraints: java.lang.Integer upper bounds: java.lang.CharSequence
Якщо це повідомляється як помилка, чому Integer x = getCharSequence();
ні?
Integer x = getCharSequence();
складеться, але кастинг на RHSInteger x = (Integer) getCharSequence();
не вдасться скласти