在运行时指定泛型集合类型参数(Java Reflection)

geg*_*ege 5 java reflection

我想在运行时使用反射来获取集合的泛型类型.

代码(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)) {
   }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法在运行时在java中获取集合的泛型类型?在我的情况下,我需要集合的泛型类型.class.

提前致谢!

Jon*_*eet 17

类型擦除意味着在执行时不存在关于对象的泛型类型的信息.

(链接到Angelika Langer的Java Generics FAQ的相关部分,该部分应该回答几乎所有关于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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果该字段位于T具有该字段的类中,List<T>那么您必须知道该实例的类型参数,以便知道该集合的类型参数.

将其转换为您需要的代码有点棘手 - 您真的需要知道集合类中的类型参数.例如,如果有人声明:

public class StringCollection implements Collection<String>
Run Code Online (Sandbox Code Playgroud)

然后有一个类型的字段StringCollection,该字段本身不会有任何类型参数.然后,您需要检查getGenericSuperTypegetGenericInterfaces递归,直到找到您想要的内容.

尽管这是可能的,但这样做真的不容易.如果我是你,我会尝试改变你的设计,这样你就不需要了.


Dar*_*roy 9

你绝对可以做你想做的事.类型擦除意味着您无法检查集合的实例是否为其泛型类型,但您当然可以检查字段的泛型类型.

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;
   }
}
Run Code Online (Sandbox Code Playgroud)

这里有很多可能出错的东西,例如,如果你有的话

Class Thing<T> {
  List<T> foo;
}
Run Code Online (Sandbox Code Playgroud)

那以上就不行了.