Подтвердить что ты не робот

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

При создании экземпляров ArrayLists я привык видеть такой код

ArrayList<Type> arr = new ArrayList<Type>();

или

ArrayList<Type> arr = new ArrayList<>();

однако сегодня я столкнулся с экземпляром ArrayList, который выглядит так:

ArrayList<Type> arr = new <Type>ArrayList();

что происходит, и почему это дает предупреждение о небезопасных операциях?

4b9b3361

Ответ 1

Edit:

Да, нашел ссылку. См. JLS & sect; 15.12.2.1 - Определение потенциально применимых методов:

Если вызов метода включает явные аргументы типа и член является обобщенным методом, то число аргументов типа равно к числу параметров типа метода.

  • В этом разделе подразумевается, что не общий метод может быть потенциально применимый к вызову, который предоставляет аргументы явного типа. Действительно, это может оказаться применимым. В этом случае тип аргументы просто игнорируются.

Акцент на мой.

Также см. JLS & sect; 15.9.3 - Выбор конструктора и его аргументов, чтобы понять, как разрешен вызов конструктора. В нем также упоминается, что вышеупомянутый процесс применяется для разрешения.


Оригинальный ответ:

Такой тип вызова часто требуется, когда у вас есть общий конструктор, а компилятор не может вывести правильные аргументы типа. Например, рассмотрите приведенный ниже код:

class Demo<T> {
    public <X> Demo(X[] arg1, X arg2) { 
        // initialization code
        System.out.println(arg1.getClass());
        System.out.println(arg2.getClass());
    }
}

Предположим, вы вызываете этот конструктор следующим образом:

Demo<String> demo = new Demo<String>(new String[2], new Integer(5));

Вы могли бы подумать, что вывод типа должен завершиться неудачно, поскольку аргументы типа должны иметь одинаковые типы. Здесь мы передаем типы String и Integer. Но это не так. Компилятор описывает тип X как:

Object & Serializable & Comparable<? extends Object&Serializable&Comparable<?>>

Теперь вам может потребоваться, чтобы параметр типа был выведен как просто Object, тогда в этом случае вы можете указать явные аргументы типа, как в приведенном ниже коде:

Demo<String> demo = new <Object>Demo<String>(new String[2], new Integer(5));

Это похоже на то, как вы указываете явный аргумент типа при вызове метода.

Теперь, в вашем коде, вы указали явные аргументы типа, но для его экземпляра используется необработанный тип класса:

ArrayList<Integer> arr = new <String>ArrayList();

<String> - это явный аргумент типа для конструктора, и компилятор будет в порядке с ним. Но проблема в том, что вы создаете исходный тип ArrayList, и именно здесь компилятор дает ваше предупреждение. Если вы измените этот код на:

ArrayList<Integer> arr = new <String>ArrayList<>();

Предупреждение исчезнет. Но так как конструктор ArrayList не является общим конструктором, аргумент типа просто игнорируется конструктором. На самом деле здесь нет аргументов типа.

Как ни странно, это также компилируется:

public static void test() { }

public static void main(String... args) {
    Main.<Integer>test();
}

... даже если test() является не общим методом.

Ответ 2

Я только что попробовал:

ArrayList<Integer> arr = new <String>ArrayList();

И получил то же предупреждение (не ошибка!). Похоже, что компилятор игнорирует 1 общие данные после ключевого слова new и перед ArrayList. Это как письмо:

ArrayList<Integer> arr = new ArrayList();

1 Я не уверен, действительно ли это "игнорирует", я буду рад, если кто-то подтвердит/исправит меня.

Ответ 3

Код, он ничего не делает!

int a = new <String>Integer(5);

Он также компилируется, но генерирует предупреждение о "неиспользуемых генериках".

Таким образом, в основном это бесполезно, но не настолько плохо, чтобы генерировать ошибку по умолчанию. В любом случае ваш arraylist НЕ надлежащим образом генерируется здесь.

Обратите внимание, что генерические файлы скомпилированы в любом случае, поэтому на уровне байт-кода он, вероятно, не будет выглядеть иначе. Я заглянул в eclipse для того, чтобы превратить это в ошибку вместо предупреждения, но не повезло там.

UPDATE

Этот ответ сводится к тому же, что и к другому, который в настоящее время находится на +5, поэтому почему мой минус? Пожалуйста, оставьте комментарий, если вы используете downvote.