繁体   English   中英

检测不同ClassLoader加载的类的Class对象等效性

[英]Detecting Class object equivalence for classes loaded by different ClassLoaders

我的任务是为方法findSubClassImplementation编写单元测试,该方法返回给定Class对象的实例。 方法签名如下所示:

public <T extends SuperClass> T findSubClassImplementation(Class<T> cls) throws Exception 

该方法在内部检查所提供的Class对象是否属于一组已知的类,然后返回该类的实例:

if (Subclass.class.equals(cls)) 
        return (T) new Subclass(args);

如果该类未知,则引发Exception。 该代码给出

我试图通过反射加载从SuperClass类继承的所有类,然后将它们作为参数传递给findSubClassImplementation

Set<Class<? extends SuperClass>> subTypesOf = reflections.getSubTypesOf(SuperClass.class);
Class<? extends SuperClass> clazz = subTypesOf.iterator().next();
SuperClass instance = findSubClassImplementation(clazz);

然后,我使用Debugger进入该方法,然后可以看到以下代码行:

if (Subclass.class.equals(cls)) 

返回错误,尽管cls = Subclass.class

我假设发生了什么: Class未实现equals,因此使用了equals的Object ,与“ ==”进行比较。 由于反射使用的类加载器不同于findSubClassImplementation使用的类加载器,因此两个类对象是不同的。 这个假设正确吗?

是否可以为我已使用反射加载的类获取另一个Class对象? 您还有其他想法如何处理此问题吗?

回答:

事实证明,我不太擅长阅读:层次结构分为3个级别:超类->中级抽象类->子类。 总是与中间抽象类进行比较:

if (IntermediateAbstractClass.class.equals(cls)) return (T) new Subclass(args);

因此,我的问题不是非常准确或精确-如果您觉得我浪费了时间,对不起。 我将迈克尔·威尔斯的答案标记为正确的答案,因为他的建议促使我发现了我的误会。 谢谢!

也许您不需要检查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);
}

这些类肯定有一些不同之处...

您说Subclass.equals(otherSubclass)返回false,我们需要确定为什么会这样。

检查每个类的名称是否相等,然后检查每个类的类加载器是否相等。

根据您提供的用于执行反射的代码,这里没有任何暗示这实际上是由“反射”加载的这些类是从不同的类加载器加载的。

此外,尝试各种类型的类,也许该类的某些独特之处会导致这种行为。

可以尝试的一种建议是将Integer添加到子类集中,然后将Number传递给该方法...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM