Объединение сырых типов и общих методов

Вот вопрос, этот первый список кодов компилируется просто отлично (JDK 1.6 | JDK 1.7):

ArrayList a = new ArrayList(); String[] s = a.toArray(new String[0]); 

Однако, если я объявляю ссылку List как необработанный тип:

 ArrayList a = new ArrayList(); String[] s = a.toArray(new String[0]); 

Я получаю ошибку компилятора, указывающую, что String[] требуется, но Object[] был найден.

Это означает, что мой компилятор интерпретирует общий метод как возвращающий Object[] несмотря на получение в качестве аргумента String[] .

Я дважды проверял подпись метода toArray(myArray) :

  T[] toArray(T[] a); 

Поэтому это параметризованный метод, параметр типа имеет никакого отношения к classу List (т.е. ).

Я понятия не имею, как использование необработанного типа влияет на оценку параметризованных методов с использованием независимых параметров типа.

  • Кто-нибудь знает, почему этот код не компилируется?
  • Кто-нибудь знает какую-либо ссылку, где это поведение документировано?

    Это не совсем то, что вы ожидаете, но если вы ссылаетесь на общий class в необработанном виде, вы теряете возможность использовать дженерики каким-либо образом, например, для членов. Это также не ограничивается общими методами, проверьте это:

      public class MyContainer { public List strings() { return Arrays.asList("a", "b"); } } MyContainer container = new MyContainer(); List strings = container.strings(); //gives unchecked warning! 

    Это соответствующая часть JLS ( 4.8 ):

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

    Когда вы не используете generics, компилятор рассматривает его как необработанный тип, и поэтому каждый родовой тип становится Object и поэтому вы не можете передать String[] поскольку ему нужен Object[]
    Итак, вот сделка – если вы используете

     List l = new ArrayList(); 

    Вы используете raw- тип, и все его экземпляры заменяются его аналогами стирания. В частности, каждый параметризованный тип, появляющийся в объявлении метода экземпляра, заменяется его исходной копией. Подробнее см. JLS 4.8.

    Это самое близкое описание, которое я нашел в спецификации для описания этого наблюдаемого поведения:

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

    Это ошибка времени компиляции для передачи параметров фактического типа члену нестатического типа необработанного типа, который не унаследован от его суперclassов или суперинтерфейсов.

    Исходя из вышеизложенного и наблюдаемого поведения, я думаю, что можно с уверенностью сказать, что все типовые типы параметров удаляются из необработанного типа. Разумеется, использование самих типов raw не рекомендуется в коде, не принадлежащем устаревшему:

    Использование типов raw допускается только в качестве уступки совместимости устаревшего кода. Использование необработанных типов в коде, написанном после введения родословности в язык программирования Java, настоятельно не рекомендуется. Возможно, что будущие версии языка программирования Java будут запрещать использование необработанных типов .

    Может быть интересно, что такое поведение можно «решить». Используйте два интерфейса, базовый не общий интерфейс и общий интерфейс. Тогда компилятор знает, что все функции базового не общего интерфейса не являются общими и будут относиться к ним так.

    Такое поведение очень раздражает, если вы используете streamи и цепочки функций, и поэтому я решаю это как следующее.

    Soution через наследование интерфейса :

     public interface GenericInterface extends BaseInterface { X getValue(); } public interface BaseInterface { String getStringValue(); } 

    Теперь вы можете делать следующее без предупреждения или проблем:

     GenericInterface object = ...; String stringValue = object.getStringValue(); 

    Параметр типа не передается в метод toArray (), так как ваш ArrayList является непараметрированным списком, он знает только, что он содержит объекты, вот и все. a.toArray() всегда возвращает массив Object []. Опять же, вы должны отдать его (String[]) (со всеми опасностями в нем), если вы хотите указать, что он содержит определенный тип String.

    Interesting Posts

    VirtualBox – гостевой Ubuntu теряет DNS, когда хост подключается к VPN

    Почему результаты Redirect не разрешены в дочерних действиях в Asp.net MVC 2

    Как создать постоянный пользовательский значок на панели задач Windows?

    В чем разница между «безопасным удалением» и «выбросом»?

    Создайте строго типизированный объект c # из объекта json с ID как имя

    Bluetooth G7 не обнаружен вообще

    Массовое удаление в LINQ для объектов

    Как я могу переделать и форматировать «USB-накопитель USB-накопителя Toshiba USB 2.0», содержащий раздел CDFS?

    Понимание ошибок ограничения значения F #

    Использование addMouseListener () и paintComponent () для JPanel

    Почему один из моих двух мониторов Dell неожиданно переходит в режим энергосбережения при использовании DisplayPort daisychaining?

    Какова версия командной строки Windows 7 для удаления всех паролей помнить в Credential Manager?

    Что я должен знать о Structured Exceptions (SEH) в C ++?

    Измените одно значение на основе другого значения в пандах

    Как заблокировать файл в Windows без его изменения или использования сторонних инструментов?

    Давайте будем гением компьютера.