Je semble avoir un malentendu sur la différence entre <Foo>
et <? extends Foo>
. D'après ma compréhension, si nous avions
ArrayList<Foo> foos = new ArrayList<>();
Cela indique que des objets de type Foo
peuvent être ajoutés à cette liste de tableaux. Comme les sous-classes de Foo
sont également de type Foo
, elles peuvent également être ajoutées sans erreur, comme illustré par
ArrayList<Foo> foos = new ArrayList<>();
foos.add(new Foo());
foos.add(new Bar());
où Bar extends Foo
.
Maintenant, disons que j'avais défini foos
comme
ArrayList<? extends Foo> foos = new ArrayList<>();
Ma compréhension actuelle est que cela s'exprime some unknown type that extends Foo
. Je suppose que cela signifie que tous les objets qui sont une sous-classe de Foo
peuvent être ajoutés à cette liste; ce qui signifie qu'il n'y a pas de différence entre ArrayList<Foo>
et ArrayList<? extends Foo>
.
Pour tester cela, j'ai essayé d'écrire le code suivant
ArrayList<? extends Foo> subFoos = new ArrayList<>();
subFoos.add(new Foo());
subFoos.add(new Bar());
mais a été invité avec l'erreur de compilation suivante
no suitable method found for add(Foo)
method java.util.Collection.add(capture#1 of ? extends Foo) is not applicable
(argument mismatch; Foo cannot be converted to capture#1 of ? extends Foo)
no suitable method found for add(Bar)
method java.util.Collection.add(capture#2 of ? extends Bar) is not applicable
(argument mismatch; Bar cannot be converted to capture#2 of ? extends Bar)
Sur la base de ma compréhension actuelle, je peux voir pourquoi je ne pourrais pas être en mesure d'ajouter un Foo
à une liste de <? extends Foo>
, car ce n'est pas une sous-classe en soi; mais je suis curieux de savoir pourquoi je ne peux pas ajouter un Bar
à la liste.
Où est le trou dans ma compréhension?
<? extends Foo>
est une classe spécifique et inconnue qui s'étendFoo
. Une opération avec cette classe n'est légale que si elle est légale pour n'importe quelle sous-classe deFoo
.Réponses:
Comme vous l'avez découvert par vous-même, un
ArrayList
as déclaréArrayList<? extends Foo> subFoos = new ArrayList<>();
ne serait pas très utile.Afin de voir l'utilité de
<? extends T>
considérer ceci:qui peut ensuite être utilisé comme suit:
ou comme suit:
noter qu'aucune de ces réponses n'aurait fonctionné si la
collect
méthode avait été déclarée comme suit:la source