Como posso conseguir isso?
public class GenericClass<T>
{
public Type getMyType()
{
//How do I return the type of T?
}
}
Tudo o que tentei até agora sempre retorna o tipo, Object
e não o tipo específico usado.
java
generics
reflection
Glenn
fonte
fonte
Respostas:
Como outros mencionaram, só é possível através da reflexão em determinadas circunstâncias.
Se você realmente precisa do tipo, este é o padrão comum de solução alternativa (com segurança de tipo):
fonte
Foo foo1 = GetDao<Foo>(Foo.class).get(Foo.class, 1)
public static <T> GenericClass<T> of(Class<T> type) {...}
e, em seguida, chamá-lo como tal:GenericClass<String> var = GenericClass.of(String.class)
. Um pouco melhor.Eu vi algo parecido com isto
no exemplo GenericDataAccessObjects hibernar
fonte
class A implements Comparable<String>
, o parâmetro de tipo real éString
, mas NÃO PODE dizer que emSet<String> a = new TreeSet<String>()
, o parâmetro de tipo real éString
. De fato, as informações do parâmetro type são "apagadas" após a compilação, conforme explicado em outras respostas.java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
esta resposta.Class-Mate
o pessoal de Jackson. Eu escrevi uma essência aqui gist.github.com/yunspace/930d4d40a787a1f6a7d1(Class<T>) ((ParameterizedType)getClass().getSuperclass().getGenericSuperclass()).getActualTypeArguments()
para obter argumentos de tipo reais.Os genéricos não são reificados em tempo de execução. Isso significa que as informações não estão presentes no tempo de execução.
Adicionar genéricos ao Java e manter a compatibilidade com versões anteriores foi um tour de force (você pode ver o documento seminal sobre o assunto: Tornando o futuro seguro para o passado: adicionando genéricos à linguagem de programação Java ).
Há uma rica literatura sobre o assunto, e algumas pessoas estão insatisfeitas com o estado atual, outros dizem que, na verdade, é uma atração e não há necessidade real disso. Você pode ler os dois links, eu os achei bastante interessantes.
fonte
Use goiaba.
Há algum tempo, publiquei alguns exemplos completos, incluindo classes abstratas e subclasses aqui .
Nota: isso requer que você instancia uma subclasse de
GenericClass
para que possa ligar o parâmetro type corretamente. Caso contrário, ele retornará o tipo comoT
.fonte
java.lang.IllegalArgumentException: class com.google.common.reflect.TypeToken isn't parameterized
. Então eu mudei a linhanew TypeToken(getClass()) { }
paranew TypeToken<T>(getClass()) { }
. Agora, o código funciona bem, mas o Type ainda é 'T'. Veja isto: gist.github.com/m-manu/9cda9d8f9d53bead2035default Type getParameterType() { final TypeToken<T> typeToken = new TypeToken<T>(getClass()) {}; final Type type = typeToken.getType(); return type; }
GenericClass
, você deve fazer essa classeabstract
para que o uso errado não seja compilado.Certamente você pode.
Java não usa as informações no tempo de execução, por motivos de compatibilidade com versões anteriores. Mas as informações estão realmente presentes como metadados e podem ser acessadas via reflexão (mas ainda não são usadas para verificação de tipo).
A partir da API oficial:
http://download.oracle.com/javase/6/docs/api/java/lang/reflect/ParameterizedType.html#getActualTypeArguments%28%29
No entanto , para o seu cenário, eu não usaria a reflexão. Pessoalmente, estou mais inclinado a usar isso como código de estrutura. No seu caso, eu apenas adicionaria o tipo como um parâmetro do construtor.
fonte
Os genéricos Java geralmente são em tempo de compilação, isso significa que as informações do tipo são perdidas no tempo de execução.
será compilado para algo como
Para obter as informações de tipo em tempo de execução, você deve adicioná-las como argumento do ctor.
Exemplo:
fonte
private final Class<T> type;
Type t = //String[]
fonte
Eu usei a seguinte abordagem:
fonte
Eu não acho que você pode, o Java usa apagamento de tipo ao compilar para que seu código seja compatível com aplicativos e bibliotecas que foram criadas pré-genéricas.
No Oracle Docs:
http://docs.oracle.com/javase/tutorial/java/generics/erasure.html
fonte
Técnica descrita neste artigo por Ian Robertson funciona para mim.
Em resumo, exemplo rápido e sujo:
fonte
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
Eu acho que há outra solução elegante.
O que você deseja fazer é (com segurança) "passar" o tipo do parâmetro de tipo genérico da classe concerete para a superclasse.
Se você se permitir pensar no tipo de classe como "metadados" na classe, isso sugere o método Java para codificar metadados no tempo de execução: anotações.
Primeiro defina uma anotação personalizada ao longo destas linhas:
Você pode adicionar a anotação à sua subclasse.
Então você pode usar este código para obter o tipo de classe na sua classe base:
Algumas limitações dessa abordagem são:
PassedGenericType
) em DOIS lugares, em vez de um que não seja SECO.fonte
Esta é a minha solução:
fonte
Aqui está a solução de trabalho !!!
OBSERVAÇÕES: Pode ser usado apenas como superclasse
1. Deve ser estendido com a classe digitada (
Child extends Generic<Integer>
)OU
2. Deve ser criado como implementação anônima (
new Generic<Integer>() {};
)fonte
Você não pode. Se você adicionar uma variável de membro do tipo T à classe (você nem precisa inicializá-la), poderá usá-la para recuperar o tipo.
fonte
Aqui está uma maneira, que eu tive que usar uma ou duas vezes:
Junto com
fonte
Uma solução simples para esta cabine é como abaixo
fonte
Para concluir algumas das respostas aqui, tive que obter o ParametrizedType de MyGenericClass, não importa quão alta seja a hierarquia, com a ajuda da recursão:
fonte
Aqui está o meu truque:
fonte
T
é uma variável de tipo. No caso deT
uma variável de tipo, as varargs criam uma matriz de apagamento deT
. Veja, por exemplo, http://ideone.com/DIPNwd .No caso de você usar armazenar uma variável usando o tipo genérico, você pode resolver facilmente esse problema adicionando um método getClassType da seguinte maneira:
Uso o objeto de classe fornecido posteriormente para verificar se é uma instância de uma determinada classe, da seguinte maneira:
fonte
value
fornull
? Em segundo lugar, e sevalue
for uma subclasse deT
?Constant<Number> c = new Constant<Number>(new Integer(0)); Class<Number> n = c.getClassType();
retornaInteger.class
quando deveria retornarNumber.class
. Seria mais correto retornarClass<? extends T>
.Integer.class
é umClass<? extends Number>
mas não umClass<Number>
.Aqui está a minha solução
Não importa quantos níveis sua hierarquia de classes tenha, esta solução ainda funciona, por exemplo:
Nesse caso, getMyType () = java.lang.String
fonte
Exception in thread "main" java.lang.NullPointerException at Main$ClassA.findTypeArguments(Main.java:54) at Main$ClassA.findTypeArguments(Main.java:54) at Main$ClassA.findTypeArguments(Main.java:54) at Main$ClassA.<init>(Main.java:43) at Main.main(Main.java:61)
fonte
Aqui está a minha solução. Os exemplos devem explicar isso. O único requisito é que uma subclasse deve definir o tipo genérico, não um objeto.
fonte
Fiz o mesmo que o @Moesio Above, mas em Kotlin isso poderia ser feito da seguinte maneira:
fonte
Pode ser útil para alguém. Você pode usar java.lang.ref.WeakReference; por aqui:
fonte
WeakReference
? Forneça alguma explicação com sua resposta, não apenas algum código.SomeClass<MyClass>
pode instanciarSomeClass
e chamargetType
nessa instância e ter o tempo de execução atualMyClass
.WeakReference
? O que você disse não é diferente da maioria das outras respostas.AtomicReference
,List
,Set
).Achei que era uma solução simples, compreensível e facilmente explicável
fonte
(T...t)
. (É por isso que esse código não funciona).