我有一个特定的目标类型(在运行时确定),还有一个与之比较的可迭代类。我正在尝试编写一种检查类的泛型参数的方法,以查看它是否是可迭代对象类型的可迭代对象。例子:
Class<?> X = SomeObject.class;
matches(X, new ArrayList<SomeObject>()) -> true
matches(X, new ArrayList<SubclassOfSomeObject>()) -> true
matches(X, new ArrayList<SomeOtherObject>()) -> false
matches(X, new ArrayList()) -> true (I think?)
matches(X, new Iterable<SomeObject>() { ... }) -> true
matches(X, new ListOfSomeObjects()) -> true
(where ListOfSomeObjects extends Iterable<SomeObject>)
不幸的是,由于类型擦除和反射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.Serializable
java.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
尚未解析。给定类型擦除,这是完全可以理解的-在运行时对应于的字节码指令new ArrayList<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 nothing
java.util.ArrayList<sandbox.SomeObject> implements:
interface java.util.List with type args: [E]
interface java.util.RandomAccess
interface java.lang.Cloneable
interface java.io.Serializable
java.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
(或子接口),然后向下爬回直到与相应的类型参数匹配。不幸的是,我不认为这将如何实现。类可以随意使用任何名称和所需的顺序声明类型参数,因此可以不进行基于名称或位置的幼稚匹配。也许其他人可以提供解决方案。
问题内容: 好吧,这是一个复杂的问题,我完全迷失了。 假设您有一个字符串和一个通用类。像这样。 您将如何检查String是否表示该类可以相等的值。 例如,可以这样说: 如何检查字符串“ true”实际上是布尔值? 这是另一个例子。可以这样说: 如何检查字符串“ true”不是整数? 问题答案: 鉴于您只需要 Wrapper Types ,可以在此处使用一些反射技巧(为简洁起见,忽略无关代码的异常处
问题内容: 我需要保留Swift元类型的集合并编写一个函数,该函数将检查给定对象是否是其中之一的实例。我可以在Java中轻松做到这一点: 但是,我不知道如何在Swift中做到这一点: 这甚至可以在Swift中完成吗? 问题答案: 不幸的是,您目前只能对运算符使用命名类型,还不能对其使用任意的元类型值(尽管实际上 应该 可以使用IMO )。 假设您可以控制要与之进行比较的元类型的创建,则达到相同结果
检查给定行是否为java代码的正确方法是什么? 输入:日志支持。java:44 com/sun/activation/registries/LogSupport日志(Ljava/lang/String;)五、 预期输出:false。 输入:扫描仪输入=新扫描仪(系统输入); 预期输出:true。 我尝试了EclipseJDTASTParser来检查是否可以创建AST。代码如下: 但这是行不通的。有
我有一个数组,它由组成。我想对它进行迭代,并找到所有作为数组实例的元素。 如何在Swift中检查对象是否属于给定类型?
问题内容: 下面的代码不适用于某些输入。 我最初的想法是检查每个输入是否为2的幂,方法是从1开始乘以2直到超过输入数量,然后在每个步骤进行比较。相反,我预先存储了2的所有幂,以便检查中的给定输入。如何改善呢? 问题答案: 将 _ 最好的,最准确_ 的方法是使用位操作: 说明: 2的每个幂将1位恰好设置为1(该数的对数以2为底的索引中的位)。因此,当从中减去1时,该位翻转为0,而所有在前位翻转为
我试图检查一个给定的二叉树是否是二叉查找树。我要做的是对二叉树进行有序遍历,并将当前元素与前一个元素进行比较。如果当前元素更大,我们继续进一步检查,否则给定的树是无效的。 这是我写的代码。我到底做错了什么?