Search code examples
javareflectionclassloaderequals

Detecting Class object equivalence for classes loaded by different ClassLoaders


My Task is to write a unit test for a method findSubClassImplementation that returns an instance for a given Class object. The method signature looks like this:

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

Internally the method checks wether the supplied Class object belongs to a set of known classes and then returns an instance of that class:

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

If the class is not known, an Exception is thrown. This code is given

I tried to load all Classes inheriting from SuperClass via Reflection and then pass them as argument to findSubClassImplementation:

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

I then use a Debugger to step into the method, and I can see the line of code where

if (Subclass.class.equals(cls)) 

returns false, although cls = Subclass.class

I assume what happens is this: Class does not implement equals, thus equals of Object is used, that compares with "==". As reflection uses a different ClassLoader than is used in findSubClassImplementation the two class Objects are different. Is this assumption correct?

Is it possible to get the other Class object for a class that I have loaded with Reflection? Do you have another idea how to deal with this problem?

ANSWER:

Turns out I am not very good at reading: The hirarchy is in 3 levels: SuperClass --> IntermediateAbstractClass--> Subclass. The comparison is always to the intermediate abstract class:

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

Thus my question wasn't very accurate or precise - I am sorry if you feel like I wasted your time. I'll mark Michael Wiles answer as the correct one, because his advice pushed my to discover my missunderstanding. Thank you!


Solution

  • There must be something that is different about the classes...

    You say that Subclass.equals(otherSubclass) returns false we need to ascertain why this is the case.

    Check the name of each class for equality and then check the classloader of each class for equality.

    Based on your provided code to do the reflection there is nothing here to sugggest that these classes loaded by "Reflection" are in fact loaded from different classloaders.

    Furthermore try all sorts of classes, maybe there is something unique about that particular class that causes the behaviour.

    One suggestion to try would be to add Integer to the subclass set and then pass in Number to the method...