Como pegar tipo generico de uma collection por reflection?

7 respostas
M

Tenho uma classe:

public class Dispositivo{

@Atributo
String id;

String desc;

}

eu preciso verificar quais os atributos desta classe é marcada com a annotation @Atributo, mas essa classe esta em um ArrayList em outra classe, por exemplo:

public class Ativos{
ArrayList<Dispositivo> list = new ArrayList<Dispositivo>();

Como eu pegaria a classe que que esta no ArrayList…

se eu usar o metodo getGenericType() ele me retorna um Type:

java.util.ArrayList

oque eu podeira fazer, pq eu não terei certeza da classe que está no array.

7 Respostas

T

mchiareli:

o que eu podeira fazer, pq eu não terei certeza da classe que está no array.

Ora, se você tem um List e não fez nenhum cast que causou warning, deve ter apenas objetos da classe Dispositivo ou de suas subclasses.

S

mchiareli:

oque eu podeira fazer, pq eu não terei certeza da classe que está no array.

Não tem como fazer isso que vc quer pq os tipos são apagados depois da compilação. Eles não ficam no codigo como os annotations, por isso não tem como usar reflection.

M

mas eu nao vou saber qual o tipo generico declarado, esse foi um exemplo simples apenas…

T

Ou seja: você não consegue saber se o objeto é da classe Dispositivo sem usar um “instanceof” em tempo de execução. De qualquer maneira, você pode chamar, para cada membro da classe do objeto, o método getAnnotations() ou isAnnotationPresent()

S

Veja:

public class ProcuraAttributos {


        public static Set<Field> procuraAttributosEm(Class class){
                /* aqui usa os métodos de Class para encontrar todos os Field
                 E depois usas os métodos isAnnotated de 
                 Field para saber se está anotada com @Atributo */

        } 

        public static Set<Field> procuraAttributosEm(Collection<T>  col) {
      // col é uma colecao de qq tipo de objeto
// repare que <T> obriga que a coleção seja de um so tipo de objecto e portanto so precisa analiza o primeiro item. Se a colecção estiver vazia, não faz mal porque o Set tb estará. 

       if (col.isEmpty()){
             return Collections.emptySet();
       } 

       Object obj = col.iterator.next();

      return  procuraAttributosEm(obj.getClass());
                                   

}

Deu para entender ? Na verdade não precisa de saber qual é a classe de T

M

sergiotaborda:
Veja:

public class ProcuraAttributos {


        public static Set<Field> procuraAttributosEm(Class class){
                /* aqui usa os métodos de Class para encontrar todos os Field
                 E depois usas os métodos isAnnotated de 
                 Field para saber se está anotada com @Atributo */

        } 

        public static Set<Field> procuraAttributosEm(Collection<T>  col) {
      // col é uma colecao de qq tipo de objeto
// repare que <T> obriga que a coleção seja de um so tipo de objecto e portanto so precisa analiza o primeiro item. Se a colecção estiver vazia, não faz mal porque o Set tb estará. 

       if (col.isEmpty()){
             return Collections.emptySet();
       } 

       Object obj = col.iterator.next();

      return  procuraAttributosEm(obj.getClass());
                                   

}

Deu para entender ? Na verdade não precisa de saber qual é a classe de T

deu pra entender sim kra…mas eu tenho um Field que representa uma collection

como eu pego a collection em sim que eh representado por esse field para interar sobre ela para verificar os atributos nos objetos que estão nela??

tipo tenho um field

Field field
field.getType() = ArrayList;

blz…

como eu tenho acesso aos objetos dentro deste arraylist??

S

deu pra entender sim kra…mas eu tenho um Field que representa uma collection

como eu pego a collection em sim que eh representado por esse field para interar sobre ela para verificar os atributos nos objetos que estão nela??

tipo tenho um field

Field field
field.getType() = ArrayList;

como eu tenho acesso aos objetos dentro deste arraylist??

Ah! Bom , isso é só fazer …

List lista = (List)  field.get(instancia);

onde field é o campo obtido dos metados e instancia é um objeto da classe em causa. E depois usa o outro código que falei.
Isto só funciona se vc tiver um objeto da classe.
Se não tiver, ou se quiser usar apenas os metadados, o que vc quer fazer não é possivel. A solução nesse caso seria criar um anotação que especifica a classe , ou super-classe, dos itens na lista algo assim

public class EstaClasse {

      @ListItemType (type=OutraClasse.class) 
      private List<T extends OutraClasse> lista;

}

A funcionalidade disto é limitada,pois obriga T a ser de uma certa classe,o que pode não ser possivel/desejável. Dependendo do que vc está tentando fazer pode ser a solução ou não.

Criado 23 de março de 2007
Ultima resposta 27 de mar. de 2007
Respostas 7
Participantes 3