Estou usando o Eclipse para me ajudar a limpar algum código para usar os genéricos Java corretamente. Na maioria das vezes, ele faz um excelente trabalho de inferir tipos, mas há alguns casos em que o tipo inferido deve ser o mais genérico possível: Objeto. Mas o Eclipse parece estar me dando uma opção para escolher entre um tipo de Objeto e um tipo de '?'.
Então, qual é a diferença entre:
HashMap<String, ?> hash1;
e
HashMap<String, Object> hash2;
Respostas:
Uma instância de
HashMap<String, String>
correspondências,Map<String, ?>
mas nãoMap<String, Object>
. Digamos que você queira escrever um método que aceite mapas deString
s para qualquer coisa: Se você escrevervocê não pode fornecer a
HashMap<String, String>
. Se você escreverfunciona!
Uma coisa às vezes incompreendida nos genéricos de Java é que esse
List<String>
não é um subtipo deList<Object>
. (Mas,String[]
na verdade, é um subtipo deObject[]
, essa é uma das razões pelas quais genéricos e matrizes não se misturam bem. (Matrizes em Java são covariantes, genéricos não, são invariantes) )).Exemplo: se você gostaria de escrever um método que aceite
List
s deInputStream
s e subtipos deInputStream
, você escreveriaA propósito: O Java eficaz de Joshua Bloch é um excelente recurso quando você deseja entender as coisas não tão simples em Java. (Sua pergunta acima também é abordada muito bem no livro.)
fonte
Outra maneira de pensar sobre esse problema é que
é equivalente a
Associe esse conhecimento ao "Princípio de obtenção e colocação " na seção (2.4) de Java Generics and Collections :
e o curinga pode começar a fazer mais sentido, espero.
fonte
HashMap<String, ? extends Object>
por isso, apenas impedenull
a adição no hashmap?É fácil entender se você se lembra de que
Collection<Object>
é apenas uma coleção genérica que contém objetos do tipoObject
, masCollection<?>
é um supertipo de todos os tipos de coleções.fonte
As respostas acima da covariância cobrem a maioria dos casos, mas perdem uma coisa:
"?" inclui "Objeto" na hierarquia de classes. Você poderia dizer que String é um tipo de Objeto e Objeto é um tipo de? Nem tudo corresponde ao objeto, mas tudo corresponde?
fonte
Você não pode colocar nada com segurança
Map<String, ?>
, porque não sabe que tipo de valores devem ser.Você pode colocar qualquer objeto em um
Map<String, Object>
, porque o valor é conhecido como umObject
.fonte
Map<String,Integer>
. SomenteInteger
objetos devem colocar armazenados no mapa como valores. Mas desde que você não sabe o tipo do valor (é?
), não sei se se é seguro para chamarput(key, "x")
,put(key, 0)
ou qualquer outra coisa.Declarar
hash1
comoHashMap<String, ?>
dita que a variávelhash1
pode conter qualquer umaHashMap
que tenha uma chaveString
e qualquer tipo de valor.Todas as opções acima são válidas, porque a variável
map
pode armazenar qualquer um desses mapas de hash. Essa variável não se importa com o tipo Value, do hashmap que ela contém.Ter um curinga que não , no entanto, deixar você colocar qualquer tipo de objeto em seu mapa. de fato, com o mapa de hash acima, você não pode colocar nada usando a
map
variável:Todas as chamadas de método acima resultarão em um erro em tempo de compilação porque o Java não sabe qual é o tipo Value do HashMap
map
.Você ainda pode obter um valor do mapa de hash. Embora você "não saiba o tipo do valor" (porque não sabe que tipo de mapa de hash está dentro da sua variável), você pode dizer que tudo é uma subclasse
Object
e, portanto, o que quer que você saia do mapa será do tipo Objeto:O bloco de código acima imprimirá 10 no console.
Portanto, para finalizar, use a
HashMap
com curingas quando você não se importa (ou seja, não importa) quais são os tipos deHashMap
, por exemplo:Caso contrário, especifique os tipos que você precisa:
No método acima, precisaríamos saber que a chave do mapa é uma
Character
, caso contrário, não saberíamos que tipo usar para obter valores dela. Todos os objetos têm umtoString()
método, no entanto, para que o mapa possa ter qualquer tipo de objeto para seus valores. Ainda podemos imprimir os valores.fonte