Ответ 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()
является не общим методом.