获取java.util.List的泛型类型

获取java.util.List的泛型类型,java,generics,Java,Generics,我有 List-stringList=new-ArrayList(); List integerList=new ArrayList(); 有没有(简单的)方法来检索列表的泛型类型?简短回答:没有 这可能是重复的,现在找不到合适的 Java使用称为类型擦除的东西,这意味着在运行时两个对象是等价的。编译器知道列表包含整数或字符串,因此可以维护类型安全环境。此信息在运行时丢失(基于对象实例),并且列表仅包含“对象” 您可以了解一些关于类的信息,它可以由哪些类型参数化,但通常这只是扩展“对象”的任何

我有

List-stringList=new-ArrayList();
List integerList=new ArrayList();
有没有(简单的)方法来检索列表的泛型类型?

简短回答:没有

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

Java使用称为类型擦除的东西,这意味着在运行时两个对象是等价的。编译器知道列表包含整数或字符串,因此可以维护类型安全环境。此信息在运行时丢失(基于对象实例),并且列表仅包含“对象”

您可以了解一些关于类的信息,它可以由哪些类型参数化,但通常这只是扩展“对象”的任何内容,即任何内容。如果将类型定义为

List<String> stringList = new ArrayList<String>();
List<Integer> integerList = new ArrayList<Integer>();
类AClass{….}

AClass.class将只包含参数A受MyClass限制的事实,但除此之外,没有办法判断。

正如其他人所说,唯一正确的答案是“否”,类型已被删除

如果列表中的元素数量不为零,则可以调查第一个元素的类型(例如,使用它的getClass方法)。这不会告诉您列表的泛型类型,但是可以合理地假设泛型类型是列表中类型的某个超类


我不提倡这种方法,但在某种情况下,它可能是有用的。

通常是不可能的,因为
List
List
共享同一个运行时类


不过,您可能能够对保存列表的字段的声明类型进行反思(如果声明的类型本身并不引用您不知道其值的类型参数)。

如果这些字段实际上是某个类的字段,则您可以通过反思获得它们:

class <A extends MyClass> AClass {....}
封装测试;
导入java.lang.reflect.Field;
导入java.lang.reflect.ParameterizedType;
导入java.util.ArrayList;
导入java.util.List;
公开课考试{
List stringList=新建ArrayList();
List integerList=new ArrayList();
公共静态void main(字符串…参数)引发异常{
Field stringListField=Test.class.getDeclaredField(“stringList”);
ParameteredType stringListType=(ParameteredType)stringListField.getGenericType();
类stringListClass=(类)stringListType.getActualTypeArguments()[0];
System.out.println(stringListClass);//class java.lang.String。
fieldintegerlistfield=Test.class.getDeclaredField(“integerList”);
ParameteredType integerListType=(ParameteredType)integerListField.getGenericType();
类integerListClass=(类)integerListType.getActualTypeArguments()[0];
System.out.println(integerListClass);//类java.lang.Integer。
}
}
对于参数类型和方法的返回类型也可以这样做


但是如果它们在类/方法的同一范围内,您需要了解它们,那么了解它们就没有意义了,因为您已经自己声明了它们。

在运行时,不,您不能

但是,通过反射可以访问类型参数。试一试

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.
    }
}

方法
getGenericType()
返回类型对象。在本例中,它将是
ParameterizedType
的一个实例,该实例又有方法
getRawType()
(在本例中,该方法将包含
List.class
)和
getActualTypeArguments()
,它们将返回一个数组(在本例中,长度为1,包含
String.class
Integer.class
)。

您也可以对方法参数执行相同操作:

for(Field field : this.getDeclaredFields()) {
    System.out.println(field.getGenericType())
}
methodmethod=someClass.getDeclaredMethod(“someMethod”);
Type[]types=method.getGenericParameterTypes();
//现在假设方法的第一个参数是List类型
ParameteredType pType=(ParameteredType)类型[0];
类clazz=(类)pType.getActualTypeArguments()[0];
System.out.println(clazz);//打印出java.lang.Integer
导入org.junit.Assert;
导入org.junit.Test;
导入java.lang.reflect.Field;
导入java.lang.reflect.ParameterizedType;
导入java.util.ArrayList;
导入java.util.Collection;
导入java.util.List;
公共类GenericTypeOfCollectionTest{
公共类FormBean{
}
公共类MyClazz{
私有列表=新的ArrayList();
}
@试验
public void testName()引发异常{
Field[]fields=MyClazz.class.getFields();
用于(字段:字段){
//1.检查字段是否为集合类型
if(Collection.class.isAssignableFrom(field.getType())){
//2.获取字段的通用类型
类fieldGenericType=getFieldGenericType(字段);
//3.与
Assert.assertTrue(“列表”,
isAssignableFrom(fieldGenericType));
}
}
}
//返回任何字段的泛型类型
公共类getFieldGenericType(字段){
if(ParameteredType.class.isAssignableFrom(field.getGenericType().getClass())){
参数化类型genericType=
(ParameterizedType)字段。getGenericType();
返回((类)
(genericType.getActualTypeArguments()[0]).getSuperclass();
}
//返回要与ValueObject和FormBean进行比较的伪布尔类
返回新的布尔值(false).getClass();
}
}

只有当集合中确实包含对象时,集合的泛型类型才有意义,对吗?那么,仅仅执行以下操作不是更容易吗:

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(fieldGenericType));
            }
        }
    }

    //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();
    }
}
您甚至可以创建一个实用程序方法,以确保列表仅包含与特定类匹配的项:

List<Number> numbers = myCollection.stream()
    .filter(Number.class::isInstance)
    .map(Number.class::cast)
    .collect(Collectors.toList());
public List getTypeSafeItemList(集合输入,类cls){
返回input.stream()
.filter(cls::isInstance)
.map(cls::cast)
.collect(Collectors.toList());
}
如果您需要
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
Map<Class<?>, List<Object>> classObjectMap = myCollection.stream()
    .filter(Objects::nonNull)
    .collect(Collectors.groupingBy(Object::getClass));

// Process the list of the correct class, and/or handle objects of incorrect
// class (throw exceptions, etc). You may need to group subclasses by
// filtering the keys. For instance:

List<Number> numbers = classObjectMap.entrySet().stream()
        .filter(e->Number.class.isAssignableFrom(e.getKey()))
        .flatMap(e->e.getValue().stream())
        .map(Number.class::cast)
        .collect(Collectors.toList());
List<Number> numbers = myCollection.stream()
    .filter(Number.class::isInstance)
    .map(Number.class::cast)
    .collect(Collectors.toList());
public <V> List<V> getTypeSafeItemList(Collection<Object> input, Class<V> cls) {
    return input.stream()
            .filter(cls::isInstance)
            .map(cls::cast)
            .collect(Collectors.toList());
}
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]);
                    }
                }
            }
        }

    }

}
/** 
* 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<? super 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);
   }
}
((Class)((ParameterizedType)field.getGenericType()).getActualTypeArguments()[0]).getSimpleName()
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");
       }
    }
}