检测由不同ClassLoader加载的类的Class对象等价

时间:2016-01-22 10:21:30

标签: java reflection classloader equals

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

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

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

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

如果该类未知,则抛出异常。 此代码

我尝试通过Reflection加载从SuperClass继承的所有类,然后将它们作为参数传递给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)) 

返回false,尽管cls = Subclass.class

我假设发生的事情是:Class没有实现等于,因此使用Object的等于,与&#34; ==&#34;相比较。由于反射使用与findSubClassImplementation中使用的不同的ClassLoader,因此两个类对象是不同的。这个假设是否正确?

是否有可能为我用Reflection加载的类获取另一个Class对象?你有另外的想法如何处理这个问题?

答案:

原来我不太擅长阅读:hirarchy有3个级别:SuperClass - &gt; IntermediateAbstractClass - &GT;子类。比较始终是中间抽象类:

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

因此我的问题不准确或准确 - 如果你觉得我浪费了你的时间,我很抱歉。我将Michael Wiles的答案标记为正确答案,因为他的建议促使我发现了我的误解。谢谢!

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

类别必须有不同的东西......

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

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

根据您提供的代码进行反射,这里没有任何内容可以说明“反射”加载的这些类实际上是从不同的类加载器加载的。

此外,尝试各种类,也许有一些特殊类可以导致行为。

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