У меня возникли некоторые проблемы при навигации по правилу Java для определения параметров универсального типа. Рассмотрим следующий класс, который имеет необязательный параметр списка:
import java.util.Collections;
import java.util.List;
public class Person {
private String name;
private List<String> nicknames;
public Person(String name) {
this(name,Collections.emptyList());
}
public Person(String name,List<String> nicknames) {
this.name = name;
this.nicknames = nicknames;
}
}
Мой компилятор Java выдает следующую ошибку:
Person.java:9: The constructor Person(String, List<Object>) is undefined
Но Collections.emptyList()
возвращает тип <T> List<T>
, а не List<Object>
. Добавление актеров не помогает
public Person(String name) {
this(name,(List<String>)Collections.emptyList());
}
доходность
Person.java:9: inconvertible types
Использование EMPTY_LIST
вместоemptyList()
public Person(String name) {
this(name,Collections.EMPTY_LIST);
}
доходность
Person.java:9: warning: [unchecked] unchecked conversion
Принимая во внимание, что следующее изменение устраняет ошибку:
public Person(String name) {
this.name = name;
this.nicknames = Collections.emptyList();
}
Может кто-нибудь объяснить, с каким правилом проверки типов я здесь сталкиваюсь, и как лучше обойти это? В этом примере последний пример кода является удовлетворительным, но с более крупными классами я хотел бы иметь возможность писать методы, следуя этому шаблону «необязательного параметра», без дублирования кода.
Для дополнительного кредита: когда уместно использовать EMPTY_LIST
в отличие от emptyList()
?
источник
Ответы:
Проблема, с которой вы сталкиваетесь, заключается в том, что, несмотря на то, что метод
emptyList()
возвращаетсяList<T>
, вы не предоставили ему тип, поэтому по умолчанию он возвращаетсяList<Object>
. Вы можете предоставить параметр type, и ваш код будет работать так, как ожидается:Теперь, когда вы делаете прямое присваивание, компилятор может определить параметры обобщенного типа для вас. Это называется вывод типа. Например, если вы сделали это:
тогда
emptyList()
вызов правильно вернул быList<String>
.источник
this
должен быть первым оператором в конструкторе.Вы хотите использовать:
Если вы посмотрите на источник для того, что emptyList вы видите, что он на самом деле просто делает
источник
метод emptyList имеет следующую подпись:
То, что
<T>
перед словом List означает, что оно выводит значение универсального параметра T из типа переменной, которой присвоен результат. Итак, в этом случае:Затем на возвращаемое значение явно ссылается переменная типа
List<String>
, так что компилятор может это выяснить. В таком случае:Для компилятора не существует явной возвращаемой переменной для определения универсального типа, поэтому по умолчанию используется значение
Object
.источник