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!
Maybe you don't need to check what class is cls
, since cls
already contains all the information you need. Try simply with
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);
}
Or in the Java 8 way:
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);
}
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...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.