栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

对于任何给定的T,如何使用Java反射来检查给定的类是否实现Iterable

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

对于任何给定的T,如何使用Java反射来检查给定的类是否实现Iterable

不幸的是,由于类型擦除和反射API的限制相结合,您要尝试的工作非常复杂。

这是真的,你可以使用的组合获得了超类的通用参数

Class.getGenericSuperclass
ParameterizedType.getActualTypeArguments
。这是例如Guava
TypeToken
类用于捕获通用类型参数的机制。但是,您要的是接口的通用类型参数,该参数可能已在继承链的任何位置实现了,尽管接口本身可以在自由解析或声明新类型参数的同时彼此继承。

为了演示,请采用以下方法:

static void inspect(Object o) {    Type type = o.getClass();    while (type != null) {        System.out.print(type + " implements");        Class<?> rawType =     (type instanceof ParameterizedType)     ? (Class<?>)((ParameterizedType)type).getRawType()     : (Class<?>)type;        Type[] interfaceTypes = rawType.getGenericInterfaces();        if (interfaceTypes.length > 0) { System.out.println(":"); for (Type interfaceType : interfaceTypes) {     if (interfaceType instanceof ParameterizedType) {         ParameterizedType parameterizedType = (ParameterizedType)interfaceType;         System.out.print("  " + parameterizedType.getRawType() + " with type args: ");         Type[] actualTypeArgs = parameterizedType.getActualTypeArguments();         System.out.println(Arrays.toString(actualTypeArgs));     }     else {         System.out.println("  " + interfaceType);     } }        }        else { System.out.println(" nothing");        }        type = rawType.getGenericSuperclass();    }}

这将反映一个对象,并爬升其继承链以报告其已实现的接口及其通用参数(如果适用)。

让我们在您列出的第一种情况下尝试一下:

inspect(new ArrayList<SomeObject>());

打印:

class java.util.ArrayList implements:  interface java.util.List with type args: [E]  interface java.util.RandomAccess  interface java.lang.Cloneable  interface java.io.Serializablejava.util.AbstractList<E> implements:  interface java.util.List with type args: [E]java.util.AbstractCollection<E> implements:  interface java.util.Collection with type args: [E]class java.lang.Object implements nothing

您可以看到type参数

E
尚未解析。给定类型擦除,这是完全可以理解的-在运行时对应于的字节码指令
newArrayList<SomeObject>()
没有概念
SomeObject

匿名类的情况不同:

inspect(new Iterable<SomeObject>() {    @Override    public Iterator<SomeObject> iterator() {        throw new UnsupportedOperationException();    }});

印刷品:

class sandbox.Main$1 implements:  interface java.lang.Iterable with type args: [class sandbox.SomeObject]class java.lang.Object implements nothing

在这里,由于匿名类通过实现解析了类型参数,因此在运行时可以使用类型参数

Iterable<SomeObject>
ListOfSomeObjects
它的任何子类都可以出于相同的原因工作。

好的,只要继承链中的某个类

E
一路解析了类型参数,我们就可以进行匹配吗?不幸的是,没有,至少不是以上方法:

inspect(new ArrayList<SomeObject>() { });

打印:

class sandbox.Main$1 implements nothingjava.util.ArrayList<sandbox.SomeObject> implements:  interface java.util.List with type args: [E]  interface java.util.RandomAccess  interface java.lang.Cloneable  interface java.io.Serializablejava.util.AbstractList<E> implements:  interface java.util.List with type args: [E]java.util.AbstractCollection<E> implements:  interface java.util.Collection with type args: [E]class java.lang.Object implements nothing

您可以看到的type参数

ArrayList
已知为
SomeObject
,但这就是它的停止位置。类型参数之间没有连接关系。原因是这段代码:

Class<?> rawType =        (type instanceof ParameterizedType)        ? (Class<?>)((ParameterizedType)type).getRawType()        : (Class<?>)type;Type[] interfaceTypes = rawType.getGenericInterfaces();

getGenericInterfaces
是获取接口的类型参数信息的唯一方法,但是该方法是由
Class
而不是声明的
Type
。只要该方法有一个
ParameterizedType
实例,该实例拥有表示其子类的通用性的状态,就会被强制调用
getRawType
,它返回
Class
没有类型实参信息的单例。这是一个问题22,导致只能获得使用具体类型实参实现的接口的类型实参。

我不知道任何将类型实参与它们解析的参数匹配的反射API方法。从理论上讲,可以编写反射性代码,使其爬上继承链,找到实现的类

Iterable
(或子接口),然后向下爬回直到与相应的类型参数匹配。不幸的是,我不认为这将如何实现。类可以随意使用任何名称和所需的顺序声明类型参数,因此可以不进行基于名称或位置的幼稚匹配。也许其他人可以提供解决方案。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/617114.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号