获取java.util.List的泛型类型
我有;
List stringList = new ArrayList();
List integerList = new ArrayList();
是否有(简单)方法来检索列表的泛型类型?
14个解决方案
349 votes
如果那些实际上是某个类的字段,那么你可以通过一些反思来获得它们:
package test;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
public class Test {
List stringList = new ArrayList();
List integerList = new ArrayList();
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.
}
}
您也可以为参数类型和返回方法类型执行此操作。
但是如果它们在你需要了解它们的类/方法的相同范围内,那么就没有必要知道它们,因为你已经自己声明了它们。
BalusC answered 2019-03-04T07:38:21Z
17 votes
您也可以对方法参数执行相同的操作:
Type[] types = method.getGenericParameterTypes();
//Now assuming that the first parameter to the method is of type List
ParameterizedType pType = (ParameterizedType) types[0];
Class> clazz = (Class>) pType.getActualTypeArguments()[0];
System.out.println(clazz); //prints out java.lang.Integer
tsaixingwei answered 2019-03-04T07:38:45Z
16 votes
简答:不。
这可能是重复的,现在找不到合适的。
Java使用称为类型擦除的东西,这意味着在运行时两个对象都是等价的。 编译器知道列表包含整数或字符串,因此可以维护类型安全的环境。 此信息在运行时丢失(基于对象实例),列表仅包含“对象”。
你可以找到一些关于类的信息,可以通过参数化来查找类型,但通常这只是扩展“对象”的任何东西,即任何东西。 如果将类型定义为
class AClass {....}
AClass.class只包含参数A受MyClass限制的事实,但更重要的是,没有办法说明。
falstro answered 2019-03-04T07:39:37Z
9 votes
如果你需要获得返回类型的泛型类型,当我需要在返回Collection的类中查找方法然后访问它们的泛型类型时,我使用了这种方法:
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 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]);
}
}
}
}
}
}
这输出:
泛型类型是类java.lang.String
Aram Kocharyan answered 2019-03-04T07:40:11Z
8 votes
要查找一个字段的泛型类型:
((Class)((ParameterizedType)field.getGenericType()).getActualTypeArguments()[0]).getSimpleName()
Mohsen Kashi answered 2019-03-04T07:40:35Z
7 votes
集合的泛型类型应该只有它实际上有对象,对吧? 所以不是更容易做到:
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
在运行时没有泛型类型的东西,但运行时内部的对象保证与声明的泛型相同,所以在处理它之前只需测试项的类就很容易了。
Steve K answered 2019-03-04T07:41:06Z
6 votes
扩展Steve 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 List super T> castListSafe(List> data, Class listType){
List 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 contains the expected type.
List foo = (List)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){
for(Foo foo: List){
System.out.println(Foo);
}
}
aMethod(List bar){
for(Bar bar: List){
System.out.println(Bar);
}
}
ggb667 answered 2019-03-04T07:41:31Z
4 votes
在运行时,不,你不能。
但是通过反射可以访问类型参数。 尝试
for(Field field : this.getDeclaredFields()) {
System.out.println(field.getGenericType())
}
方法getGenericType()返回Type对象。 在这种情况下,它将是ParametrizedType的实例,其反过来有方法getRawType()(在这种情况下将包含List.class)和getActualTypeArguments(),它将返回一个数组(在这种情况下,长度为1,包含String.class或Integer.class)。
Scott Morrison answered 2019-03-04T07:42:14Z
4 votes
有同样的问题,但我使用了instanceof。 这样做了:
List listCheck = (List)(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");
}
}
}
这涉及使用未经检查的强制转换,因此只有当您知道它是一个列表时才会执行此操作,以及它可以是什么类型。
Andy answered 2019-03-04T07:42:49Z
3 votes
一般不可能,因为List和List共享相同的运行时类。
您可能能够反映持有列表的字段的声明类型(如果声明的类型本身不引用您不知道其值的类型参数)。
meriton answered 2019-03-04T07:43:23Z
2 votes
正如其他人所说,唯一正确的答案是否定的,这种类型已被删除。
如果列表具有非零数量的元素,则可以调查第一个元素的类型(例如,使用它的getClass方法)。 这不会告诉你列表的泛型类型,但是假设泛型类型是列表中类型的某些超类是合理的。
我不会提倡这种方法,但是在绑定中它可能是有用的。
Chris Arguin answered 2019-03-04T07:44:09Z
1 votes
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 list = new ArrayList();
}
@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
Assert.assertTrue("List",
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();
}
}
Ashish answered 2019-03-04T07:44:31Z
0 votes
类型被删除,所以你将无法。 见[http://en.wikipedia.org/wiki/Type_erasure]和[http://en.wikipedia.org/wiki/Generics_in_Java#Type_erasure]
peter.murray.rust answered 2019-03-04T07:45:00Z
0 votes
使用Reflection获取Field然后你可以这样做:field.genericType获取包含有关泛型信息的类型。
Siddharth Shishulkar answered 2019-03-04T07:45:28Z