it-swarm.com.de

Collections.emptyList () gibt eine Liste <Object> zurück?

Ich habe einige Probleme beim Navigieren in Javas Regel, um auf generische Typparameter zu schließen. Betrachten Sie die folgende Klasse mit einem optionalen Listenparameter:

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

Mein Java Compiler gibt den folgenden Fehler aus:

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

Aber Collections.emptyList() gibt den Typ <T> List<T> Zurück, nicht List<Object>. Das Hinzufügen einer Besetzung hilft nicht

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

ausbeuten

Person.Java:9: inconvertible types

Verwenden von EMPTY_LIST Anstelle von emptyList()

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

ausbeuten

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

Während die folgende Änderung den Fehler beseitigt:

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

Kann jemand erklären, gegen welche Typüberprüfungsregel ich hier stoße und wie ich das am besten umgehen kann? In diesem Beispiel ist das endgültige Codebeispiel zufriedenstellend, aber bei größeren Klassen möchte ich in der Lage sein, Methoden nach diesem "optionalen Parameter" -Muster zu schreiben, ohne Code zu duplizieren.

Für zusätzliches Guthaben: Wann ist es angebracht, EMPTY_LIST Anstelle von emptyList() zu verwenden?

254
Chris Conway

Das Problem, auf das Sie stoßen, ist, dass die Methode emptyList() zwar List<T> zurückgibt, Sie sie jedoch nicht mit dem Typ versehen haben. Daher wird standardmäßig List<Object> zurückgegeben. . Sie können den Typparameter angeben und Ihren Code wie folgt verhalten lassen:

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

Wenn Sie jetzt eine direkte Zuweisung durchführen, kann der Compiler die generischen Typparameter für Sie ermitteln. Es heißt Typinferenz. Wenn Sie dies zum Beispiel getan haben:

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

dann würde der emptyList() -Aufruf korrekt einen List<String> zurückgeben.

430
InverseFalcon

Sie möchten verwenden:

Collections.<String>emptyList();

Wenn Sie die Quelle nach dem suchen, was emptyList tut, sehen Sie, dass es tatsächlich nur ein tut

return (List<T>)EMPTY_LIST;
95
carson

die Methode emptyList hat folgende Signatur:

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

Das <T> Vor der Wortliste bedeutet, dass der Wert des generischen Parameters T aus dem Variablentyp abgeleitet wird, dem das Ergebnis zugewiesen ist. Also in diesem Fall:

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

Der Rückgabewert wird dann explizit von einer Variablen vom Typ List<String> Referenziert, damit der Compiler es herausfinden kann. In diesem Fall:

setList(Collections.emptyList());

Es gibt keine explizite Rückgabevariable, die der Compiler verwenden kann, um den generischen Typ herauszufinden. Der Standardwert ist Object.

26
Dan Vinton