Указание универсального типа коллекции param во время выполнения (Java Reflection) - PullRequest
5 голосов
/ 15 июля 2009

Я хотел бы получить общий тип коллекции, используя отражение, во время выполнения.

Код (JAVA):

Field collectionObject = object.getClass().getDeclaredField(
    collectionField.getName());
//here I compare to see if a collection
if (Collection.class.isAssignableFrom(collectionObject.getType())) {
   // here I have to use the generic type of the collection 
   // to see if it's from a specific type - in this case Persistable
   if (Persistable.class.isAssignableFrom(GENERIC_TYPE_COLLECTION.class)) {
   }
}

Есть ли способ получить универсальный тип коллекции в java во время выполнения? В моем случае мне нужен .class универсального типа коллекции.

Заранее спасибо!

Ответы [ 4 ]

17 голосов
/ 15 июля 2009

Стирание типа означает, что информация об универсальном типе объекта просто отсутствует во время выполнения.

(Ссылка на соответствующий раздел часто задаваемых вопросов по Java Generics * от Angelika Langer , который должен ответить практически на каждый вопрос, который вы можете задать о дженериках Java :)

Однако вам не очень интересен тип объекта - вас интересует тип поля . Я неправильно понял вопрос, и хотя ответ был принят, я надеюсь исправить ситуацию, исправив ее сейчас:)

Если поле не использует сам параметр типа, это можно сделать. Например:

import java.lang.reflect.*;
import java.util.*;

public class Test
{
    public List<String> names;

    public static void main(String [] args)
        throws Exception // Just for simplicity!
    {
        Field field = Test.class.getDeclaredField("names");

        ParameterizedType type = (ParameterizedType) field.getGenericType();

        // List
        System.out.println(type.getRawType());

        // Just String in this case
        for (Type typeArgument : type.getActualTypeArguments())
        {
            System.out.println("  " + typeArgument);
        }
    }
}

Если бы поле было в классе T с полем List<T>, вам нужно было бы знать аргумент типа для экземпляра, чтобы узнать аргумент типа для коллекции.

Перевод этого в требуемый код несколько сложен - вам действительно нужно знать аргумент типа в точке класса коллекции. Например, если кто-то объявил:

public class StringCollection implements Collection<String>

и затем имеет поле типа StringCollection, само поле не будет иметь аргументов типа. Затем вам нужно будет проверять getGenericSuperType и getGenericInterfaces рекурсивно, пока вы не найдете то, что хотели.

Это действительно не будет легко сделать, даже если это возможно. Если бы я был тобой, я бы попытался изменить твой дизайн, чтобы он тебе не понадобился.

9 голосов
/ 15 июля 2009

Вы можете делать абсолютно то, что хотите. Стирание типа означает, что вы не можете проверить экземпляр коллекции на предмет ее универсального типа, но вы, безусловно, можете проверить поле на его универсальный тип.

class Thing {
  List<Persistable> foo;
}


Field f = Thing.class.getDeclaredField("foo");
if( Collection.class.isAssignableFrom( f.getType() ) {
   Type t = f.getGenericType();
   if( t instanceof ParameterizedType ) {
     Class genericType = (Class)((ParameterizedType)t).getActualTypeArguments()[0];
     if( Persistable.class.isAssignableFrom( genericType ) )
         return true;
   }
}

Есть много вещей, которые могут пойти не так, например, если у вас есть

Class Thing<T> {
  List<T> foo;
}

тогда вышеописанное не будет работать.

0 голосов
/ 15 июля 2009

Скопировано с моего поста по адресу: /873365/obschii-klass-java-opredelenie-tipa#873382

Я использовал решение, подобное тому, что он объясняет здесь для нескольких проектов, и нашел его довольно полезным.

http://blog.xebia.com/2009/02/07/acessing-generic-types-at-runtime-in-java/

Для определения параметра типа во время выполнения используется следующее:

public Class returnedClass {
  ParameterizedType parameterizedType =
    (ParameterizedType) getClass().getGenericSuperClass();
 return (Class) parameterizedtype.getActualTypeArguments()[0];
}
0 голосов
/ 15 июля 2009

Вы можете получить общий тип поля, из которого вы читаете объект, с помощью Field.getGenericType. Обратите внимание, что поле может быть необработанным типом, редким типом (универсальным, но с универсальным аргументом, который является необработанным), использовать тип экземпляра, использовать групповые символы и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...