Confusing stuff first.
My class is to do the following.
1. receive arguments and a class name
2. get the classforname
3. match the arguments to a constructor
4. construct the new class using the arguments
5. return the new class instance
I'm using reflection to construct a class from its name and arguments. Its all polymorphic and IOC. In doing so, I have designed it to find the first constructor in the "classForName" which matches the arguments supplied.
The problem I am having is with the line.
if (cArgType.equalsIgnoreCase(ctorType.getTypeName())) {
Note this is a very cut down version of my code. I cut out most of the error checking, throws and declarations which are irrelevant to make it easy to read. As such, you may come across some handles which you did not see declared.
One of the constructors.
public ClassBuilder(String cName, Object[] constructorArgs) {
this.className = cName;
this.cArgs = constructorArgs;
}
Then in the method which constructs the class
private Object builtObject() {
Class<?> cls = null;
Object handler = null;
cls = Class.forName(this.className);
List<String> cArgTypes = new ArrayList<>();
for (Object cArg : this.cArgs) {
cArgTypes.add(cArg.getClass().getName());
}
Class<?>[] ctorTypes = ctor.getParameterTypes()
for (Class<?> ctorType : ctorTypes) {
for (String cArgType : cArgTypes) {
if (cArgType.equalsIgnoreCase(ctorType.getTypeName())) {
ctorTypeMatches++;
break;
} else {
System.out.println("Typematch Fail: " + cArgType + " != " + ctorType.getName());
}
}
}
handler = clsCtor != null ? clsCtor.newInstance(this.cArgs) : cls.newInstance();
}
This code is currently throwing errors with:
Typematch Fail: au.com.mshcraft.testplugin.TestPlugin != org.bukkit.plugin.Plugin
Typematch Fail: java.util.List != java.util.ArrayList
So as you can probably see from the code, when you create a list, it is a List of type ArrayList and so its type is ArrayList. When you create a constructor, you specify that the argument passed must be of type List. So when I tried to search for the correct constructor by comparing the argument types with the parameter types, my search turned up no results. Now since I had already set the type that was to contain the constructor to null, it remained null and resulted in a NPE.
List<String> myList
with
ctor.getParameterTypes()
you are effectively comparing
java.util.List with java.util.ArrayList
So, how can I compare them correctly or is there a better way to get the first constructor that fits the arguments?
What I have tried:
instanceof but can't seem to get it to accept ctorType and cArgType as arguments to pass to instanceof.
ie:
for (Class<?> ctorType : ctorTypes) {
for (Class<?> cArgType : cArgTypes) {
if (cArgType instanceof ctorType) {
results in cArgType unknown type or undefined for something about get #15of ?
getTypeName() which is the same as name
getDeclaringClass.getName() results in null because its an array
[21:17:01] [Server thread/INFO]: getCanonicalName(): java.util.ArrayList
[21:17:01] [Server thread/INFO]: getCanonicalName(): java.util.ArrayList
[21:17:01] [Server thread/INFO]: getSuperclass(): org.bukkit.plugin.java.JavaPlugin
[21:17:01] [Server thread/INFO]: getSuperclass(): java.util.AbstractList
[21:17:01] [Server thread/INFO]: getSuperclass(): java.util.AbstractList
[21:17:01] [Server thread/INFO]: getAnnotatedSuperclass(): class org.bukkit.plugin.java.JavaPlugin
[21:17:01] [Server thread/INFO]: getAnnotatedSuperclass(): java.util.AbstractList<e>
[21:17:01] [Server thread/INFO]: getAnnotatedSuperclass(): java.util.AbstractList<e>
[21:17:01] [Server thread/INFO]: getInterfaces(): class org.bukkit.plugin.java.JavaPlugin
[21:17:01] [Server thread/INFO]: getInterfaces(): java.util.AbstractList<e>
[21:17:01] [Server thread/INFO]: getInterfaces(): java.util.AbstractList<e>