获取java.util.List的genericstypes

我有;

List<String> stringList = new ArrayList<String>(); List<Integer> integerList = new ArrayList<Integer>(); 

有没有一个(简单)的方法来检索列表的通用types?

如果这些实际上是某个class级的领域,那么可以借助一些反思来获得他们:

 package test; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.util.ArrayList; import java.util.List; public class Test { List<String> stringList = new ArrayList<String>(); List<Integer> integerList = new ArrayList<Integer>(); public static void main(String... args) throws Exception { Field stringListField = Test.class.getDeclaredField("stringList"); ParameterizedType stringListType = (ParameterizedType) stringListField.getGenericType(); Class<?> stringListClass = (Class<?>) stringListType.getActualTypeArguments()[0]; System.out.println(stringListClass); // class java.lang.String. Field integerListField = Test.class.getDeclaredField("integerList"); ParameterizedType integerListType = (ParameterizedType) integerListField.getGenericType(); Class<?> integerListClass = (Class<?>) integerListType.getActualTypeArguments()[0]; System.out.println(integerListClass); // class java.lang.Integer. } } 

你也可以为参数types和返回types的方法做到这一点。

但是,如果他们在类别/方法的相同范围内,您需要了解他们,那么就没有必要了解他们,因为您已经自己宣布了他们。

简短的回答:不。

这可能是重复的,现在找不到合适的。

Java使用了一种称为types擦除的方法,这意味着在运行时两个对象是等价的。 编译器知道列表包含整数或string,因此可以维护一个types安全的环境。 这些信息在运行时会丢失(以对象实例为基础),而列表只包含“对象”。

你可以find一些关于这个类的东西,它可能被参数化了,但通常这只是任何延伸“对象”的东西,也就是任何东西。 如果你定义一个types为

 class <A extends MyClass> AClass {....} 

AClass.class将只包含参数A被MyClass限制的事实,但更多的是,没有办法告诉。

你也可以为方法参数做同样的事情:

 Type[] types = method.getGenericParameterTypes(); //Now assuming that the first parameter to the method is of type List<Integer> ParameterizedType pType = (ParameterizedType) types[0]; Class<?> clazz = (Class<?>) pType.getActualTypeArguments()[0]; System.out.println(clazz); //prints out java.lang.Integer 

如果您需要获取返回types的genericstypes,那么当我需要在返回Collection的类中查找方法,然后访问它们的genericstypes时,我会使用这种方法:

 import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Collection; import java.util.List; public class Test { public List<String> test() { return null; } public static void main(String[] args) throws Exception { for (Method method : Test.class.getMethods()) { Class returnClass = method.getReturnType(); if (Collection.class.isAssignableFrom(returnClass)) { Type returnType = method.getGenericReturnType(); if (returnType instanceof ParameterizedType) { ParameterizedType paramType = (ParameterizedType) returnType; Type[] argTypes = paramType.getActualTypeArguments(); if (argTypes.length > 0) { System.out.println("Generic type is " + argTypes[0]); } } } } } } 

这输出:

genericstypes是java.lang.String类

扩大史蒂夫K的答案:

 /** * Performs a forced cast. * Returns null if the collection type does not match the items in the list. * @param data The list to cast. * @param listType The type of list to cast to. */ static <T> List<T> castListSafe(List<?> data, Class<T> listType){ List<T> retval = null; //This test could be skipped if you trust the callers, but it wouldn't be safe then. if(data!=null && !data.isEmpty() && listType.isInstance(data.iterator().next().getClass())) { @SuppressWarnings("unchecked")//It's OK, we know List<T> contains the expected type. List<T> foo = (List<T>)data; return retval; } return retval; } Usage: protected WhateverClass add(List<?> data) {//For fluant useage if(data==null) || data.isEmpty(){ throw new IllegalArgumentException("add() " + data==null?"null":"empty" + " collection"); } Class<?> colType = data.iterator().next().getClass();//Something aMethod(castListSafe(data, colType)); } aMethod(List<Foo> foo){ for(Foo foo: List){ System.out.println(Foo); } } aMethod(List<Bar> bar){ for(Bar bar: List){ System.out.println(Bar); } } 

在运行时,不,你不能。

但是通过reflection可以访问types参数。 尝试

 for(Field field : this.getDeclaredFields()) { System.out.println(field.getGenericType()) } 

getGenericType()方法返回一个Type对象。 在这种情况下,它将是一个ParametrizedType的实例,它依次具有方法getRawType() (在本例中包含List.class )和getActualTypeArguments() ,它们将返回一个数组(在本例中为length ,包含String.classInteger.class )。

一个集合的genericstypes应该只在实际上有对象的时候才重要,对吗? 所以,这样做并不容易:

 Collection<?> myCollection = getUnknownCollectionFromSomewhere(); Class genericClass = null; Iterator it = myCollection.iterator(); if (it.hasNext()){ genericClass = it.next().getClass(); } if (genericClass != null) { //do whatever we needed to know the type for 

在运行时没有genericstypes的东西,但运行时内部的对象保证和声明genericstypes相同,所以在处理它之前testing项目的类是很容易的。

寻找一个字段的通用types:

 ((Class)((ParameterizedType)field.getGenericType()).getActualTypeArguments()[0]).getSimpleName() 

正如其他人所说,唯一正确的答案是否定的,types已被删除。

如果列表的元素数量不是零,则可以调查第一个元素的types(例如,使用getClass方法)。 这不会告诉你列表的genericstypes,但是假设generics是列表中types的一个超类是合理的。

我不会主张这个方法,但是在一个约束中它可能是有用的。

通常不可能,因为List<String>List<Integer>共享相同的运行时类。

但是,如果声明的types本身没有引用其值不明的types参数,那么您可能会反映出声明持有该列表的字段的types。

有同样的问题,但我使用instanceof来代替。 是这样做的:

 List<Object> listCheck = (List<Object>)(Object) stringList; if (!listCheck.isEmpty()) { if (listCheck.get(0) instanceof String) { System.out.println("List type is String"); } if (listCheck.get(0) instanceof Integer) { System.out.println("List type is Integer"); } } } 

这涉及到使用未经检查的强制转换,所以只有当你知道它是一个列表时,才能做到这一点,它可以是什么types。

 import org.junit.Assert; import org.junit.Test; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.util.ArrayList; import java.util.Collection; import java.util.List; public class GenericTypeOfCollectionTest { public class FormBean { } public class MyClazz { private List<FormBean> list = new ArrayList<FormBean>(); } @Test public void testName() throws Exception { Field[] fields = MyClazz.class.getFields(); for (Field field : fields) { //1. Check if field is of Collection Type if (Collection.class.isAssignableFrom(field.getType())) { //2. Get Generic type of your field Class fieldGenericType = getFieldGenericType(field); //3. Compare with <FromBean> Assert.assertTrue("List<FormBean>", FormBean.class.isAssignableFrom(getFieldGenericTypefieldGenericType)); } } } //Returns generic type of any field public Class getFieldGenericType(Field field) { if (ParameterizedType.class.isAssignableFrom(field.getGenericType().getClass())) { ParameterizedType genericType = (ParameterizedType) field.getGenericType(); return ((Class) (genericType.getActualTypeArguments()[0])).getSuperclass(); } //Returns dummy Boolean Class to compare with ValueObject & FormBean return new Boolean(false).getClass(); } } 

使用reflection来获取这些Field ,然后你可以这样做: field.genericType以获得包含通用信息的types。