J'ai du mal à naviguer dans la règle de Java pour déduire des paramètres de type génériques. Considérez la classe suivante, qui a un paramètre de liste facultatif:
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 le type <T> List<T>
, non List<Object>
. L'ajout d'un casting n'aide pas
public Person(String name) {
this(name,(List<String>)Collections.emptyList());
}
les rendements
Person.java:9: inconvertible types
Utiliser EMPTY_LIST
au lieu deemptyList()
public Person(String name) {
this(name,Collections.EMPTY_LIST);
}
les rendements
Person.java:9: warning: [unchecked] unchecked conversion
Alors que la modification suivante fait disparaître l'erreur:
public Person(String name) {
this.name = name;
this.nicknames = Collections.emptyList();
}
Quelqu'un peut-il expliquer à quelle règle de vérification de type je me heurte ici et quelle est la meilleure façon de contourner ce problème? Dans cet exemple, l'exemple de code final est satisfaisant, mais avec des classes plus grandes, j'aimerais pouvoir écrire des méthodes suivant ce modèle de "paramètre facultatif" sans dupliquer le code.
Pour un crédit supplémentaire: quand est-il approprié d'utiliser EMPTY_LIST
par opposition à emptyList()
?
la source
Réponses:
Le problème que vous rencontrez est que même si la méthode
emptyList()
retourneList<T>
, vous ne lui avez pas fourni le type, donc elle revient par défautList<Object>
. Vous pouvez fournir le paramètre type et faire en sorte que votre code se comporte comme prévu, comme ceci:Maintenant, lorsque vous effectuez une affectation directe, 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:
alors l'
emptyList()
appel renverrait correctement aList<String>
.la source
this
doit être la première instruction du constructeur.Vous souhaitez utiliser:
Si vous regardez la source de ce que emptyList voyez-vous qu'il fait en fait juste un
la source
la méthode emptyList a cette signature:
Ce qui
<T>
précède le mot Liste signifie qu'il déduit la valeur du paramètre générique T du type de variable auquel le résultat est affecté. Donc dans ce cas:La valeur de retour est ensuite référencée explicitement par une variable de type
List<String>
, afin que le compilateur puisse la comprendre. Dans ce cas:Il n'y a pas de variable de retour explicite à utiliser par le compilateur pour déterminer le type générique, il est donc par défaut
Object
.la source