Почему использование необработанных переменных типа влияет на подписи без ссылки на параметры типа?

Взгляд в другой question Я столкнулся с этим интригующим поведением компилятора Sun-Oracle 1.8.0_112 (я не тестировал его с другими):

import java.util.List;

interface Alpha<T> {
   List<Integer> intList();
}

interface Beta {
   List<Integer> intList();
}

class Main {

   public static void main(String[] args) {

      Alpha rawAlpha = null;
      Alpha<Character> charAlpha = null;
      Alpha<?> qmAlpha = null;
      Beta beta = null;

      for (Integer i : charAlpha.intList()) {}
      for (Integer i : qmAlpha.intList()) {}
      for (Integer i : beta.intList()) {}
      for (Integer i : rawAlpha.intList()) {}
   }
}

Только компилятор не работает в последнем цикле for:

error: incompatible types: Object cannot be converted to Integer
      for (Integer i : rawAlpha.intList()) {}
                                       ^
1 error

Поэтому, несмотря на то, что тип возвращаемого списка intList() List<Integer> в Alpha не зависит от параметра типа T, кажется, что <Integer> стирается во время компиляции.

Обратите внимание: если мы объявим не общий интерфейс Beta, теоретически эквивалентным тому, чтобы ссылаться на raw Alpha, проблем нет.

Является ли это ожидаемым поведением? может ли кто-нибудь указать параграф на языке спецификации, который будет охватывать этот момент? Если это не ошибка, по крайней мере, она кажется антиинтуитивной и непродуктивной; возможно, делается ради обратной сопоставимости?

Ответ 1

Бит JLS, который говорит это (немного неясно), находится в JLS 4.8:

Тип конструктора (§8.8), метод экземпляра (§8.4, §9.4) или нестатическое поле (§8.3) необработанного типа С, которое не унаследовано от его суперклассов или суперинтерфейсов, является необработанным типом что соответствует стиранию его типа в общем объявлении, соответствующем C.

Итак, поскольку rawAlpha является сырым типом, типом rawAlpha.intList является стирание List<Integer> intList(). Это стирание List intList().

Что касается причин, у меня нет ссылки, но сырые типы действительно на самом деле в Java для обратной совместимости. Это означает, что они должны работать только так, как раньше, до дженериков; то, о чем вы просите, это код, который работает немного лучше, чем раньше. Это не необоснованно, но это не то, что они решили.: -)