如何通过反射获取 List<T>中泛型 T 的真实类型?

2021-11-09 10:23:13 +08:00
 7911364440
public class PageResult<T> {

    private int total;
    private List<T> data;

    public static <T> PageResult<T> of(Page<T> page) {
        return new PageResult<>(page.getSize(), page.getContent());
    }

}
5035 次点击
所在节点    Java
35 条回复
zongren
2021-11-09 10:24:55 +08:00
好像获取不到吧,只能把 class 传进来
chendy
2021-11-09 10:35:42 +08:00
看你的需求
如果只是想看看 List 里面是啥,取第一个元素看一眼类型就行了(对空 List 无效)
v2lf
2021-11-09 10:37:02 +08:00
通过继承, 设置一个抽象的超类 ,实现这个需求
wolfie
2021-11-09 10:37:03 +08:00
泛型是编译期,反射是运行时。
orangie
2021-11-09 10:40:59 +08:00
话说,为什么当初添加泛型功能的时候,没有给添加一个字段用于保存编译时能确定的这个泛型类型呢?比如给加一个 getGenericClass()方法,编译器实现内部代码让他返回 T 的真实类型。虽然这么做好像不能用于协变和逆变,不过再加一个方法用来返回协变、逆变、准确泛型?
kiotech
2021-11-09 10:45:22 +08:00
泛型 T 可以为 interface ,即 PageResult<PageInterface>,这样就可以拿到 page.getSize(), page.getContent()
youkiiiiiiiiiiiI
2021-11-09 10:47:24 +08:00
GG
leeg810312
2021-11-09 10:47:38 +08:00
@orangie JAVA 历史遗留问题,很难改了,你说的特性只有运行时真泛型才能做到,反射是运行时,编译时泛型是做不到的
clf
2021-11-09 11:25:04 +08:00
SpringBoot 下泛型接口:
public interface IService<T> {
...
default Class<T> getClazz() {
return (Class<T>) GenericTypeResolver.resolveTypeArgument(getClass(), IService.class);
}
...
}
clf
2021-11-09 11:26:10 +08:00
@clf #9 能拿到的是 public class XXXService extends IService<XXX> {} 的 XXX.class
ZoteTheMighty
2021-11-09 11:30:30 +08:00
T 里面的类继承一个抽象类,抽象类里放一个抽象方法 getClassInfo , 然后子类实现该接口。
guyuesh2
2021-11-09 11:30:53 +08:00
Class#getDeclaredField

Field#getGenericType

ParameterizedType 和 Type 的一些子类了解一下,泛型反射是 Gson FastJson 的基础吧 !
0xZhangKe
2021-11-09 13:09:33 +08:00
可以看看 Gson 是怎么做的,就是上面说的继承会保存范型类型。
passerbytiny
2021-11-09 13:17:41 +08:00
首先给答案,不能。原因:Java 泛型仅在编译时有效,编译之后任何泛型信息都被擦除了。
passerbytiny
2021-11-09 13:24:46 +08:00
当然有折衷的方法。继承关系中会残留一些泛型信息到运行时,可以用来变相获取 T 。你不能在运行时获取 List<T>中 T 的实际类型,但是可以获取 List<T extend SomeAbstractClass/Interface>中 T 的实际类型。
passerbytiny
2021-11-09 13:28:59 +08:00
上面说错了一点,是可以获取 List<T extend SomeAbstractClass/Interface<T>>中 T 的实际类型。
INCerry
2021-11-09 13:40:20 +08:00
如果是 C#的话 直接即可
public Type GetListType<T>(List<T> list)
{
return list.GetType().GetGenericArguments()[0];
}
thetbw
2021-11-09 13:54:28 +08:00
无解,我用的就是楼上的方法,当用 aop 对参数处理的时候,遇到 list 就把 list 中的数据取出来判断类型,如果没数据,跳过
geligaoli
2021-11-09 14:02:59 +08:00
可以有变通的方式,

1. 在 PageResult<T> 的子类中获取。2. 直接 new 对象时传递 T 的类型。

public class PageResult<T> {
private Class<T> entityClass;

/**
* 子类中获取 entityClass
*/
public PageResult() {
this.entityClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}

/**
* new 对象的时候传递
*
* @param entityClass
*/
public PageResult(Class<T> entityClass) {
this.entityClass = entityClass;
}
Edsie
2021-11-09 17:03:50 +08:00
3 楼正解

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/814075

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX