282 votes

Les Collections.emptyList() renvoie une Liste<Object>?

Je vais avoir quelques problèmes de navigation de Java est la règle pour inférer les paramètres de type générique. Considérons la classe suivante, qui a une option de paramètre de liste:

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

Mon compilateur Java donne l'erreur suivante:

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

Mais Collections.emptyList() renvoie type <T> List<T>, pas List<Object>. L'ajout d'un cast n'aide pas

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

les rendements

Person.java:9: inconvertible types

À l'aide de EMPTY_LIST au lieu de emptyList()

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

les rendements

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

Considérant que la modification suivante fait disparaître l'erreur:

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

Quelqu'un peut expliquer ce type de vérification de la règle, je suis à court contre ici, et le meilleur moyen de le contourner? Dans cet exemple, le dernier exemple de code est satisfaisante, mais avec de plus grandes classes, j'aimerais être capable d'écrire des méthodes suivantes ce "paramètre facultatif" modèle sans duplication de code.

Pour le crédit supplémentaire: quand est-il approprié d'utiliser EMPTY_LIST plutôt emptyList()?

465voto

InverseFalcon Points 1906

La question que vous êtes à la rencontre, c'est que, même si la méthode emptyList() retours List<T>, vous n'avez pas fourni avec le type, de sorte que la valeur par défaut est de retour List<Object>. Vous pouvez fournir le type de paramètre, et vous avez votre code se comporter comme prévu, comme ceci:

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

Maintenant, quand vous êtes en train de faire tout droit de l'assignation, le compilateur peut déterminer les paramètres de type générique pour vous. Cela s'appelle l'inférence de type. Par exemple, si vous avez fait ceci:

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

puis l' emptyList() appel renvoyer correctement un List<String>.

107voto

carson Points 3852

Vous souhaitez utiliser:

Collections.<String>emptyList();

Si vous regardez le code source pour ce emptyList ne vous voyez qu'il fait juste un

return (List<T>)EMPTY_LIST;

27voto

Dan Vinton Points 11975

le emptyList méthode a cette signature:

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

Qu' <T> avant la Liste de mots signifie qu'il déduit la valeur du paramètre générique de T sur le type de variable le résultat est affecté. Donc dans ce cas:

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

La valeur de retour est alors explicitement référencé par une variable de type List<String>, de sorte que le compilateur peut le comprendre. Dans ce cas:

setList(Collections.emptyList());

Il n'y a pas explicitement de la variable de retour pour le compilateur à utiliser pour déterminer le type générique, de sorte que la valeur par défaut est Object.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X