Вызов универсального конструктора
Это необычно, но вполне допустимая Java.Чтобы понять, нам нужно знать, что класс может иметь универсальный конструктор, например:
public class TypeWithGenericConstructor {
public <T> TypeWithGenericConstructor(T arg) {
// TODO Auto-generated constructor stub
}
}
Я полагаю, что чаще всего при создании экземпляра класса с помощью универсального конструктора нам не нужно делатьаргумент типа явный.Например:
new TypeWithGenericConstructor(LocalDate.now(ZoneId.systemDefault()));
Теперь T
явно LocalDate
.Однако могут быть случаи, когда Java не может вывести (вывести) аргумент типа.Затем мы предоставляем его явно, используя синтаксис из вашего вопроса:
new <LocalDate>TypeWithGenericConstructor(null);
Конечно, мы можем также предоставить его, даже если в этом нет необходимости, если мы считаем, что это помогает удобочитаемости или по какой-либо причине:
new <LocalDate>TypeWithGenericConstructor(LocalDate.now(ZoneId.systemDefault()));
В вашем вопросе вы, кажется, вызываете конструктор java.util.ArrayList
.Этот конструктор не является универсальным (только класс ArrayList
в целом, это нечто другое).Почему Java позволяет вам предоставлять аргументы типа в вызове, когда они не используются, см. Мое редактирование ниже.Мой Eclipse выдает мне предупреждение :
Неиспользуемые аргументы типа для неуниверсального конструктора ArrayList () типа ArrayList;он не должен быть параметризован с аргументами
Но это не ошибка, и программа работает нормально (я дополнительно получаю предупреждения об отсутствующих аргументах типа для List
и ArrayList
, но это опять-такидругая история).
Универсальный класс по сравнению с универсальным конструктором
Имеет ли расположение аргументов типа то же значение, что и размещение их после типа?Если нет, что означает другое позиционирование?
Нет, это другое.Обычный аргумент типа / s после типа (ArrayList<Integer>()
) предназначен для универсального класса .Аргументы типа перед предназначены для конструктора .
Также можно комбинировать две формы:
List<Integer> list = new <String, Long>ArrayList<Integer>();
Я бы немного об этом подумалболее правильно, поскольку теперь мы можем видеть, что в списке хранится Integer
объектов (я бы, конечно, предпочел бы пропустить бессмысленные <String, Long>
).
Почему законно иметь 2Аргументы типа, когда ArrayList имеет только 1?
Во-первых, если вы передаете аргументы типа перед типом, вы должны указать правильный номер для конструктора, а не для класса, чтобы он ничего не получилделать с тем, сколько аргументов типа есть у класса ArrayList
.Это действительно означает, что в этом случае вы не должны указывать ничего, так как конструктор не принимает аргументы типа (он не является универсальным).Когда вы в любом случае предоставляете некоторые из них, они игнорируются, поэтому не имеет значения, сколько или сколько вы предоставляете.
Почему допустимы бессмысленные аргументы типа?
Редактируйте с помощью @Slaw для ссылки: Java допускает аргументы типа для всех вызовов методов.Если вызываемый метод является универсальным, используются аргументы типа;если нет, они игнорируются.Например:
int length = "My string".<List>length();
Да, это абсурд.Спецификация языка Java (JLS) дает это обоснование в подразделе 15.12.2.1:
Это правило вытекает из вопросов совместимости и принципов заменяемости.Поскольку интерфейсы или суперклассы могут генерироваться независимо от их подтипов, мы можем переопределить универсальный метод с неуниверсальным.Однако переопределяющий (неуниверсальный) метод должен быть применим к вызовам универсального метода, включая вызовы, которые явно передают аргументы типа.В противном случае подтип не заменим для своего обобщенного супертипа.
Аргумент не выполняется для конструкторов, поскольку их нельзя напрямую переопределить.Но я полагаю, что они хотели иметь одно и то же правило, чтобы не усложнять и без того сложные правила.В любом случае, раздел 15.9.3 об экземплярах и new
более одного раза ссылается на 15.12.2.
Ссылки