Normalmente, eu já vi pessoas usarem a classe literal assim:
Class<Foo> cls = Foo.class;
Mas e se o tipo for genérico, por exemplo, Lista? Isso funciona bem, mas possui um aviso, pois a Lista deve ser parametrizada:
Class<List> cls = List.class
Então, por que não adicionar um <?>
? Bem, isso causa um erro de incompatibilidade de tipo:
Class<List<?>> cls = List.class
Imaginei que algo assim funcionaria, mas este é apenas um simples erro de sintaxe:
Class<List<Foo>> cls = List<Foo>.class
Como posso obter Class<List<Foo>>
estaticamente, por exemplo, usando a classe literal?
Eu poderia usar @SuppressWarnings("unchecked")
para me livrar dos avisos causados pelo uso não parametrizado de List no primeiro exemplo Class<List> cls = List.class
, mas prefiro não.
Alguma sugestão?
List<Integer> list1 = new ArrayList<Integer>(); List<String> list2 = (List<String>)list1; list2.add("foo"); // perfectly legal
Você não pode fazer isso em Java, obtém um erro de compilação de incompatibilidade de tipo!List<String> list2 = (List<String>) (Object) list1;
Não existem literais de classe para tipos parametrizados, no entanto, existem objetos Type que definem corretamente esses tipos.
Consulte java.lang.reflect.ParameterizedType - http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/ParameterizedType.html
A biblioteca Gson do Google define uma classe TypeToken que permite simplesmente gerar tipos parametrizados e a utiliza para especificar objetos json com tipos parametrizados complexos de uma maneira amigável genérica. No seu exemplo, você usaria:
Pretendia postar links para as classes TypeToken e Gson javadoc, mas o Stack Overflow não me permite publicar mais de um link, já que sou um novo usuário. Você pode encontrá-los facilmente usando a Pesquisa do Google.
fonte
clzz = new TypeToken<E>(){}.getRawType();
para iterar posteriormente sobre enums com estrutura semelhanteclzz.getEnumConstants()
e, finalmente, usar a refection para chamar os métodos de membros a umaMethod method = clzz.getDeclaredMethod("getSomeFoo");
vitória tão grande! Obrigado!Você pode gerenciá-lo com um elenco duplo:
@SuppressWarnings("unchecked") Class<List<Foo>> cls = (Class<List<Foo>>)(Object)List.class
fonte
Object
para,Class
você provavelmente pode economizar a sobrecarga de uma conversão de tempo de execução verificada (sem sentido).Class
, em vez deObject
, como você sugere, parece mais significativa mas não remove a necessidade da@SuppressWarnings("unchecked")
anotação, ele ainda adicionar um novo aviso:Class is a raw type. References to generic type Class<T> should be parameterized
Class<?>
:(Class<List<Foo>>)(Class<?>)List.class
unchecked
aviso. Esta resposta não altera / melhora nada disso. OP afirma mesmo na sua pergunta que não quer usarSuppressWarnings
...Para expor a resposta do cletus, em tempo de execução, todos os registros dos tipos genéricos são removidos. Os genéricos são processados apenas no compilador e são usados para fornecer segurança de tipo adicional. Eles são realmente apenas uma abreviação que permite ao compilador inserir previsões de tipos nos locais apropriados. Por exemplo, anteriormente você teria que fazer o seguinte:
torna-se
Isso permite que o compilador verifique seu código em tempo de compilação, mas em tempo de execução ele ainda se parece com o primeiro exemplo.
fonte
As perguntas frequentes sobre o Java Generics e, portanto, também a resposta do cletus parecem não ter sentido
Class<List<T>>
, no entanto, o verdadeiro problema é que isso é extremamente perigoso:O
cast()
faz parecer que é seguro, mas na realidade não é seguro.Embora eu não chegue onde não pode haver
List<?>.class
=,Class<List<?>>
pois isso seria bastante útil quando você tem um método que determina o tipo com base no tipo genérico de umClass
argumento.Como
getClass()
há JDK-6184881 solicitando a troca de caracteres curinga, no entanto, parece que essa alteração não será executada (muito em breve), pois não é compatível com o código anterior (consulte este comentário ).fonte
Bem, como todos sabemos que é apagado. Mas pode ser conhecido em algumas circunstâncias em que o tipo é mencionado explicitamente na hierarquia de classes:
E agora você pode fazer coisas como:
Mais informações aqui . Mas, novamente, é quase impossível recuperar para:
onde é apagado.
fonte
GenericEntity
eGenericType
.Devido ao fato exposto de que literais de classe não têm informações de tipo genérico, acho que você deve assumir que será impossível se livrar de todos os avisos. De certa forma, usar
Class<Something>
é o mesmo que usar uma coleção sem especificar o tipo genérico. O melhor que pude apresentar foi:fonte
Você pode usar um método auxiliar para se livrar de
@SuppressWarnings("unchecked")
toda a classe.Então você poderia escrever
Outros exemplos de uso são
No entanto, como raramente é realmente útil e o uso do método anula a verificação de tipo do compilador, eu não recomendaria implementá-lo em um local em que seja acessível ao público.
fonte