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

获取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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值