Это реальный пример из 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();
не является?