Eu tenho uma lista que é declarada assim:
List<? extends Number> foo3 = new ArrayList<Integer>();
Eu tentei adicionar 3 ao foo3. No entanto, recebo uma mensagem de erro como esta:
The method add(capture#1-of ? extends Number) in the type List<capture#1-of ?
extends Number> is not applicable for the arguments (ExtendsNumber)
List<? extends Number>
isso não significa "lista de objetos de tipos diferentes, todos os quais estendidosNumber
". Significa "lista de objetos de um único tipo que se estendeNumber
".Respostas:
Desculpe, mas você não pode.
A declaração curinga
List<? extends Number> foo3
significa que a variávelfoo3
pode conter qualquer valor de uma família de tipos (em vez de qualquer valor de um tipo específico). Isso significa que qualquer uma dessas são atribuições legais:Portanto, considerando isso, que tipo de objeto você poderia adicionar a
List foo3
ele seria legal após qualquer uma dasArrayList
atribuições possíveis acima :Integer
porquefoo3
pode estar apontando para umList<Double>
.Double
porquefoo3
pode estar apontando para umList<Integer>
.Number
porquefoo3
pode estar apontando para umList<Integer>
.Você não pode adicionar nenhum objeto
List<? extends T>
porque não pode garantir que tipo de objetoList
ele realmente está apontando; portanto, não pode garantir que o objeto seja permitido neleList
. A única "garantia" é que você só pode ler e obter umaT
ou subclasse deT
.A lógica reversa se aplica a
super
, por exemploList<? super T>
. Estes são legais:Você não pode ler o tipo específico T (por exemplo
Number
),List<? super T>
porque não pode garantir que tipo deList
coisa realmente está apontando. A única "garantia" que você tem é que você pode adicionar um valor do tipoT
(ou qualquer subclasse deT
) sem violar a integridade da lista que está sendo apontada.O exemplo perfeito disso é a assinatura para
Collections.copy()
:Observe como a
src
declaração da lista usaextends
para permitir que eu passe qualquer lista de uma família de tipos de lista relacionados e ainda garanto que ela produzirá valores do tipo T ou subclasses de T. Mas você não pode adicionar àsrc
lista.A
dest
declaração da lista é usadasuper
para permitir a passagem de qualquer lista de uma família de tipos de lista relacionados e ainda garantir que eu possa gravar um valor de um tipo específico T nessa lista. Mas não é possível garantir a leitura dos valores do tipo específico T se eu ler a partir da lista.Portanto, agora, graças aos curingas genéricos, eu posso fazer qualquer uma dessas chamadas com esse método único:
Considere esse código confuso e muito amplo para exercitar seu cérebro. As linhas comentadas são ilegais e a razão pela qual é declarada à extrema direita da linha (é necessário rolar para ver algumas delas):
fonte
src
List
argumento usaextends
para ler da lista src, enquanto odest
List
argumento usasuper
para gravar na lista de destino. Isso permite um método que pode copiar deList<Integer>
ouList<Double>
paraList<Number>
ouList<Object>
.or subclass of T
está correto. Por exemplo, não posso adicionar umObject
(superclasse deNumber
) aList<? super Number> foo3
porquefoo3
pode ter sido atribuído como:List<? super Number> foo3 = new ArrayList<Number>
(que pode conter apenasNumber
ou subclasses deNumber
).<? super Number>
refere-se aos tipos deList<>
s aos quais pode ser atribuídofoo3
- e não aos tipos de coisas que podem ser adicionados / lidos a partir dele. Os tipos de itens que podem ser adicionados / removidosfoo3
devem ser itens que podem ser adicionados / removidos de qualquer tipo aoList<>
qual possa ser atribuídofoo3
.Você não pode (sem lançamentos inseguros). Você só pode ler a partir deles.
O problema é que você não sabe exatamente do que a lista é. Pode ser uma lista de qualquer subclasse de Number; portanto, quando você tenta inserir um elemento nele, não sabe se o elemento realmente se encaixa na lista.
Por exemplo, a lista pode ser uma lista de
Byte
s; portanto, seria um erro colocar umFloat
nela.fonte
"List '<'? Extends Number> é realmente um curinga de limite superior!
O curinga com limite superior diz que qualquer classe que estenda Number ou Number em si pode ser usada como o tipo de parâmetro formal: O problema decorre do fato de o Java não saber qual é realmente o tipo List . Tem que ser um tipo EXATO e ÚNICO. Espero que ajude :)
fonte
Você poderia fazer isso:
fonte
Foi confuso para mim, apesar de ler as respostas aqui, até encontrar o comentário de Pavel Minaev:
Depois disso, pude entender a incrível explicação de BertF. Listar <? estende Número> significa? pode ser de qualquer tipo, estendendo Number (Integer, Double, etc) e não está esclarecido na declaração (List <? extends Number> list) qual deles é; portanto, quando você deseja usar o método add, não se sabe se a entrada é do mesmo tipo ou não; qual é o tipo?
Então os elementos da List <? extends Number> só poderia ser definido ao construir.
Observe também: Quando estamos usando modelos, informamos ao compilador com que tipo estamos mexendo. T, por exemplo, mantém esse tipo para nós, mas não ? faz o mesmo
Eu tenho que dizer .. Este é um dos sujos para explicar / aprender
fonte
onde estender a lista de 'Objeto', você pode usar list.add e, quando quiser, use list.get só precisa converter Object para seu Object;
fonte