检测由不同的 ClassLoader 加载的 类 的 Class 对象等价性
Detecting Class object equivalence for classes loaded by different ClassLoaders
我的任务是为 findSubClassImplementation
方法编写单元测试,returns 给定 Class 对象的实例。方法签名如下所示:
public <T extends SuperClass> T findSubClassImplementation(Class<T> cls) throws Exception
该方法在内部检查所提供的 Class 对象是否属于一组已知的 class 对象,然后 returns 该对象的一个实例 class:
if (Subclass.class.equals(cls))
return (T) new Subclass(args);
如果 class 未知,则抛出异常。 给出此代码
我试图通过反射加载所有从 SuperClass
继承的 Classes,然后将它们作为参数传递给 findSubClassImplementation
:
Set<Class<? extends SuperClass>> subTypesOf = reflections.getSubTypesOf(SuperClass.class);
Class<? extends SuperClass> clazz = subTypesOf.iterator().next();
SuperClass instance = findSubClassImplementation(clazz);
然后我使用调试器进入该方法,我可以看到
所在的代码行
if (Subclass.class.equals(cls))
returns 错误,尽管 cls = Subclass.class
我假设发生的事情是这样的:Class
没有实现等于,因此使用了 Object
的等于,与“==”进行比较。由于反射使用的 ClassLoader 与 findSubClassImplementation
中使用的不同,因此两个 class 对象是不同的。这个假设是否正确?
是否可以为我用反射加载的 class 获取另一个 Class 对象?你有其他想法如何处理这个问题吗?
答案:
原来我不是很会看书: 层次分三级:SuperClass --> IntermediateAbstractClass--> Subclass。比较总是与中间摘要 class:
if (IntermediateAbstractClass.class.equals(cls)) return (T) new Subclass(args);
因此我的问题不是很准确或精确 - 如果您觉得我浪费了您的时间,我很抱歉。我会将 Michael Wiles 的回答标记为正确答案,因为他的建议促使我发现了我的误解。谢谢!
也许您不需要检查 class 是什么 cls
,因为 cls
已经包含了您需要的所有信息。简单地尝试
public <T extends SuperClass> T findSubClassImplementation(Class<T> cls) throws Exception {
// ... retrieve args
final Class<?>[] constructorParamTypes = new Class<?>[args.length];
for (int i = 0; i < args.length; i++) {
constructorParamTypes[i] = args[i].getClass();
}
return cls.getConstructor(constructorParamTypes).newInstance(args);
}
或者在 Java 8 种方式中:
public <T extends SuperClass> T findSubClassImplementation(Class<T> cls) throws Exception {
// ... retrieve args
final Class<?>[] constructorParamTypes = Arrays.stream(args).map(Object::getClass)
.toArray(size -> new Class<?>[size]);
return cls.getConstructor(constructorParamTypes).newInstance(args);
}
classes 一定有什么不同...
你说 Subclass.equals(otherSubclass) returns 错了,我们需要弄清楚为什么会这样。
检查每个 class 的名称是否相等,然后检查每个 class 的 classloader 是否相等。
根据您提供的进行反射的代码,这里没有任何迹象表明 "Reflection" 加载的这些 classes 实际上是从不同的 classloader 加载的。
此外,尝试各种 classes,也许导致该行为的特定 class 有一些独特之处。
一个尝试的建议是将 Integer 添加到 subclass 集,然后将 Number 传递给方法...
我的任务是为 findSubClassImplementation
方法编写单元测试,returns 给定 Class 对象的实例。方法签名如下所示:
public <T extends SuperClass> T findSubClassImplementation(Class<T> cls) throws Exception
该方法在内部检查所提供的 Class 对象是否属于一组已知的 class 对象,然后 returns 该对象的一个实例 class:
if (Subclass.class.equals(cls))
return (T) new Subclass(args);
如果 class 未知,则抛出异常。 给出此代码
我试图通过反射加载所有从 SuperClass
继承的 Classes,然后将它们作为参数传递给 findSubClassImplementation
:
Set<Class<? extends SuperClass>> subTypesOf = reflections.getSubTypesOf(SuperClass.class);
Class<? extends SuperClass> clazz = subTypesOf.iterator().next();
SuperClass instance = findSubClassImplementation(clazz);
然后我使用调试器进入该方法,我可以看到
所在的代码行if (Subclass.class.equals(cls))
returns 错误,尽管 cls = Subclass.class
我假设发生的事情是这样的:Class
没有实现等于,因此使用了 Object
的等于,与“==”进行比较。由于反射使用的 ClassLoader 与 findSubClassImplementation
中使用的不同,因此两个 class 对象是不同的。这个假设是否正确?
是否可以为我用反射加载的 class 获取另一个 Class 对象?你有其他想法如何处理这个问题吗?
答案:
原来我不是很会看书: 层次分三级:SuperClass --> IntermediateAbstractClass--> Subclass。比较总是与中间摘要 class:
if (IntermediateAbstractClass.class.equals(cls)) return (T) new Subclass(args);
因此我的问题不是很准确或精确 - 如果您觉得我浪费了您的时间,我很抱歉。我会将 Michael Wiles 的回答标记为正确答案,因为他的建议促使我发现了我的误解。谢谢!
也许您不需要检查 class 是什么 cls
,因为 cls
已经包含了您需要的所有信息。简单地尝试
public <T extends SuperClass> T findSubClassImplementation(Class<T> cls) throws Exception {
// ... retrieve args
final Class<?>[] constructorParamTypes = new Class<?>[args.length];
for (int i = 0; i < args.length; i++) {
constructorParamTypes[i] = args[i].getClass();
}
return cls.getConstructor(constructorParamTypes).newInstance(args);
}
或者在 Java 8 种方式中:
public <T extends SuperClass> T findSubClassImplementation(Class<T> cls) throws Exception {
// ... retrieve args
final Class<?>[] constructorParamTypes = Arrays.stream(args).map(Object::getClass)
.toArray(size -> new Class<?>[size]);
return cls.getConstructor(constructorParamTypes).newInstance(args);
}
classes 一定有什么不同...
你说 Subclass.equals(otherSubclass) returns 错了,我们需要弄清楚为什么会这样。
检查每个 class 的名称是否相等,然后检查每个 class 的 classloader 是否相等。
根据您提供的进行反射的代码,这里没有任何迹象表明 "Reflection" 加载的这些 classes 实际上是从不同的 classloader 加载的。
此外,尝试各种 classes,也许导致该行为的特定 class 有一些独特之处。
一个尝试的建议是将 Integer 添加到 subclass 集,然后将 Number 传递给方法...