При создании экземпляров ArrayLists я привык видеть такой код
ArrayList arr = new ArrayList();
или
ArrayList arr = new ArrayList();
однако сегодня я столкнулся с экземпляром ArrayList, который выглядит так:
ArrayList arr = new ArrayList();
что происходит, и почему это дает предупреждение о небезопасных операциях?
Редактировать:
Да, нашел ссылку. См. JLS §15.12.2.1 – Определение потенциально применимых методов :
Если вызов метода включает явные аргументы типа, а элемент – общий метод, то количество аргументов типа равно количеству параметров типа метода.
- Это предложение подразумевает, что не общий метод может быть потенциально применим к вызову, который предоставляет аргументы явного типа. Действительно, это может оказаться применимым. В таком случае аргументы типа просто игнорируются.
Акцент мой.
Также см. JLS §15.9.3 – Выбор конструктора и его аргументов для понимания того, как вызов конструктора разрешен. В нем также упоминается, что вышеупомянутый процесс применяется для разрешения.
Оригинальный ответ:
Такой тип вызова часто требуется, когда у вас есть общий конструктор, и компилятор не может вывести правильные аргументы типа. Например, рассмотрите приведенный ниже код:
class Demo { public Demo(X[] arg1, X arg2) { // initialization code System.out.println(arg1.getClass()); System.out.println(arg2.getClass()); } }
Предположим, вы вызываете этот конструктор следующим образом:
Demo demo = new Demo (new String[2], new Integer(5));
Вы могли бы подумать, что вывод типа должен завершиться неудачно, поскольку аргументы типа должны иметь одинаковые типы. Здесь мы передаем типы String
и Integer
. Но это не так. Компилятор описывает тип X
как:
Object & Serializable & Comparable extends Object&Serializable&Comparable>>
Теперь вам может потребоваться, чтобы параметр типа был выведен как просто Object
, тогда в этом случае вы можете указать явные аргументы типа, как в приведенном ниже коде:
Demo demo = new
Это похоже на то, как вы даете явный аргумент типа при вызове метода.
Теперь, в вашем коде, вы указали явные аргументы типа, но для его экземпляра используется необработанный тип classа:
ArrayList arr = new ArrayList();
– это явный аргумент типа для конструктора, и компилятор будет в порядке с ним. Но проблема в том, что вы создаете исходный тип ArrayList
, и именно здесь компилятор дает ваше безотлагательное предупреждение. Если вы измените этот код на:
ArrayList arr = new ArrayList<>();
Предупреждение исчезнет. Но так как конструктор ArrayList
не является общим конструктором, аргумент типа просто игнорируется конструктором. На самом деле здесь нет аргументов типа.
Как ни странно, это также компилируется:
public static void test() { } public static void main(String... args) { Main.test(); }
… хотя test()
– это не общий метод.
Я только что попробовал:
ArrayList arr = new ArrayList();
И получил такое же предупреждение (не ошибка!). Похоже, компилятор игнорирует 1 генерики после new
ключевого слова и перед ArrayList
. Это похоже на письмо:
ArrayList arr = new ArrayList();
1 Я не уверен, действительно ли это «игнорирует», я буду рад, если кто-то подтвердит / исправит меня
Код, он ничего не делает!
int a = new Integer(5);
Он также компилируется, но генерирует предупреждение о «неиспользуемых дженериках».
Поэтому в принципе это бесполезно, но не настолько плохо, чтобы генерировать ошибку по умолчанию. В любом случае ваш аррайалист НЕ надлежащим образом генерируется здесь.
Обратите внимание, что генерические файлы скомпилированы в любом случае, поэтому на уровне байт-кода он, вероятно, не будет выглядеть иначе. Я заглянул в затмение, чтобы превратить это в ошибку вместо предупреждения, но не повезло.
ОБНОВИТЬ
Этот ответ сводится к тому же, что и к другому, который в настоящее время находится на +5, так почему мой нисходящий? Пожалуйста, оставьте комментарий, если вы используете downvote.