O que significa o ponto de interrogação no parâmetro de tipo de genéricos Java?

Este é um pequeno trecho de código retirado de alguns dos exemplos que acompanham o Stanford Parser. Eu tenho desenvolvido em Java por cerca de 4 anos, mas nunca tive um entendimento muito forte do que este estilo de código deveria indicar.

List wordList = toke.tokenize(); 

Não estou preocupado com os detalhes do código. O que me deixa confuso é o que exatamente a expressão genérica deve transmitir em inglês.

Alguém pode explicar isso para mim?

 ? extends HasWord 

significa “Uma class / interface que estende o HasWord “. Em outras palavras, o HasWord ou qualquer um de seus filhos … basicamente qualquer coisa que funcione com instanceof HasWord mais null .

Em termos mais técnicos, ? extends HasWord é um curinga limitado, coberto no Item 31 do Effective Java 3rd Edition , iniciando na página 139. O mesmo capítulo da 2ª edição está disponível online como um PDF ; a parte em curingas limitados é Item 28, começando na página 134.

Atualização: o link do PDF foi atualizado, pois o Oracle o removeu há algum tempo. Agora, aponta para a cópia hospedada pela Escola de Engenharia Eletrônica e Ciência da Computação da Universidade Queen Mary de Londres.

Atualização 2: Vamos detalhar um pouco mais sobre por que você deseja usar curingas.

Se você declarar um método cuja assinatura espera que você passe em List , a única coisa que você pode passar é uma List .

No entanto, se essa assinatura foi List List então você poderia passar em uma List vez disso.

Note que há uma diferença sutil entre List List e List List . Como diz Joshua Bloch: PECS = produtor-se estende, consumidor-super.

O que isto significa é que se você está passando em uma coleção que seu método extrai dados (ou seja, a coleção está produzindo elementos para seu método usar), você deve usar extends . Se você está passando uma coleção na qual seu método adiciona dados (isto é, se a coleção está consumindo elementos que seu método cria), ela deve usar super .

Isso pode parecer confuso. No entanto, você pode vê-lo no comando sort ‘s List (que é apenas um atalho para a versão two-arg do Collections.sort). Em vez de tomar um Comparator , ele realmente leva um Comparator Comparator . Nesse caso, o Comparador está consumindo os elementos da List para reordenar a Lista em si.

Um ponto de interrogação é um significante para “qualquer tipo”. ? sozinho significa

Qualquer tipo de extensão de Object (incluindo Object )

enquanto o seu exemplo acima significa

Qualquer tipo de extensão ou implementação de HasWord (incluindo HasWord se HasWord for uma class não abstrata)

List List aceita qualquer class concreta que estenda o HasWord. Se você tem as seguintes classs …

 public class A extends HasWord { .. } public class B extends HasWord { .. } public class C { .. } public class D extends SomeOtherWord { .. } 

… o wordList só pode conter uma lista de As ou Bs ou mistura de ambos, porque ambas as classs estendem o mesmo pai ou null (que falha na instância de verificações para HasWorld ).

Talvez um exemplo planejado de “mundo real” ajudaria.

No trabalho, temos latas de lixo com diferentes sabores. Todas as checkboxs contêm lixo, mas algumas checkboxs são especializadas e não aceitam todos os tipos de lixo. Portanto, temos Bin e Bin . O sistema de tipos precisa ter certeza de que não posso colocar o meu HalfEatenSandwichRubbish em nenhum desses tipos, mas ele pode entrar em uma lixeira geral “Bin” . If I wanted to talk about a . If I wanted to talk about a Bin of Rubbish, which may be a specialist so I can't put in incompatible rubbish, then that would be Bin ‘.

(Observação: ? extends se não significa somente leitura”. Por exemplo, posso, com as devidas precauções, remover um pedaço de lixo de uma checkbox de especialidade desconhecida e depois colocá-lo de volta em um lugar diferente.)

Não tenho certeza de quanto isso ajuda. Ponteiro para ponteiro na presença de polymorphism não é inteiramente óbvio.

Em inglês:

É uma List de algum tipo que estende a class HasWord , incluindo HasWord

Em geral o ? em genéricos significa qualquer class. E a extends SomeClass especifica que esse object deve estender SomeClass (ou ser essa class).

O ponto de interrogação é usado para definir curingas . Verifique a documentação do Oracle sobre eles: http://docs.oracle.com/javase/tutorial/java/generics/wildcards.html