Kolekcje.emptyList () zwraca listę?

Mam problem z nawigacją w regułach Javy do wnioskowania ogólnych parametrów typu. Rozważmy następującą klasę, która ma opcjonalny parametr listy:

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;
  }
}

Mój kompilator Javy podaje następujący błąd:

Person.java:9: The constructor Person(String, List<Object>) is undefined

Ale Collections.emptyList() zwraca typ <T> List<T>, a nie List<Object>. Dodawanie obsady nie pomaga

public Person(String name) {
  this(name,(List<String>)Collections.emptyList());
}

Person.java:9: inconvertible types

Użycie EMPTY_LIST zamiast emptyList()

public Person(String name) {
  this(name,Collections.EMPTY_LIST);
}

Person.java:9: warning: [unchecked] unchecked conversion

Podczas gdy następująca zmiana powoduje, że błąd daleko:

public Person(String name) {
  this.name = name;
  this.nicknames = Collections.emptyList();
}

Czy ktoś może wyjaśnić, z jaką regułą sprawdzania typu mam tu do czynienia i jak najlepiej to obejść? W tym przykładzie końcowy przykład kodu jest zadowalający, ale przy większych klasach chciałbym móc pisać metody zgodnie z tym" opcjonalnym parametrem " bez powielania kodu.

Dla dodatkowego kredytu: Kiedy należy używać EMPTY_LIST W przeciwieństwie do emptyList()?

Author: Kai, 2008-11-20

3 answers

Napotkany problem polega na tym, że mimo że metoda emptyList() zwraca List<T>, nie podałeś jej typu, więc domyślnie zwraca List<Object>. Możesz podać parametr type i sprawić, aby Twój kod zachowywał się zgodnie z oczekiwaniami, w następujący sposób:

public Person(String name) {
  this(name,Collections.<String>emptyList());
}

Teraz, gdy robisz proste przypisanie, kompilator może obliczyć ogólne parametry typu dla Ciebie. To się nazywa wnioskowanie typu. Na przykład, jeśli to zrobiłeś:

public Person(String name) {
  List<String> emptyList = Collections.emptyList();
  this(name, emptyList);
}

Wtedy wywołanie emptyList() zwróci poprawnie List<String>.

 408
Author: InverseFalcon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-20 20:34:46

Chcesz użyć:

Collections.<String>emptyList();

Jeśli spojrzysz na źródło tego, co robi emptyList, zobaczysz, że faktycznie robi

return (List<T>)EMPTY_LIST;
 89
Author: carson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-20 20:34:38

Metoda emptyList ma taki podpis:

public static final <T> List<T> emptyList()

To <T> przed listą słów oznacza, że wyprowadza wartość parametru ogólnego T z typu zmiennej, do której jest przypisany wynik. Więc w tym przypadku:

List<String> stringList = Collections.emptyList();

Zwracana wartość jest następnie jawnie odwoływana przez zmienną typu List<String>, więc kompilator może to rozgryźć. W tym przypadku:

setList(Collections.emptyList());

Nie ma jawnej zmiennej zwrotnej, której kompilator mógłby użyć do określenia typu generycznego, więc domyślnie jest to Object.

 26
Author: Dan Vinton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-20 20:25:29