Click here to Skip to main content
15,880,469 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
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.
Java
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.
Java
public ClassBuilder(String cName, Object[] constructorArgs) {
    this.className = cName;
    this.cArgs = constructorArgs;
}


Then in the method which constructs the class
Java
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.

Java
List<String> myList

with
Java
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>
Posted
Updated 9-Jun-16 3:31am
v24
Comments
Richard MacCutchan 9-Jun-16 7:18am    
I just tried something similar and it worked fine. Which line did the error occur on, and what was the exact text of the exception message?
Michael Hurt 9-Jun-16 7:21am    
this is directly out of the log, however please also note that the comments after the NPE are what I wrote during my troubleshooting.

[21:17:01] [Server thread/ERROR]: Error occurred while enabling TestPlugin v0.0.1-SNAPSHOT (Is it up to date?)
java.lang.NullPointerException: Incorrect argument type or length in ClassBuilder constructor
at au.com.mshcraft.testplugin.ClassBuilder.builtObject(ClassBuilder.java:199) ~[?:?]
at au.com.mshcraft.testplugin.ClassBuilder.getClassObject(ClassBuilder.java:52) ~[?:?]
at au.com.mshcraft.testplugin.CommandInterpreter.<init>(CommandInterpreter.java:30) ~[?:?]
at au.com.mshcraft.testplugin.TestPlugin.onEnable(TestPlugin.java:76) ~[?:?]


This error comes from:
try {
// the decider!
if (clsCtor == null) { throw new NullPointerException("Incorrect argument type or length in ClassBuilder constructor");}
// if (cArgs == null) { throw new NullPointerException("The constructor arguments object was null");}
handler = clsCtor != null ? clsCtor.newInstance(this.cArgs) : cls.newInstance();
Richard MacCutchan 9-Jun-16 7:35am    
Since you are throwing the exception you are the only person who can figure out why clsCtor is null at that point in the code.
Michael Hurt 9-Jun-16 7:43am    
I have and I need help. This is why....

public myExample(List<string> myList) {}

The constructor now has parameter type "java.util.List"
Now lets create the list.

private List<string> myList = new ArrayList<>();

Ok, so now the list is of type "java.util.ArrayList"
So now lets compare the parameter in the constructor with the argument we just made to make sure we are passing the correct argument to the constructor.

if ("java.util.List" == "java.util.ArrayList") { doSomething() }

Whoops!
And so this is what I need help with.

if (cArgType.equalsIgnoreCase(ctorType.getTypeName())) {
ctorTypeMatches++;
break;
}
Richard MacCutchan 9-Jun-16 7:56am    
if ("java.util.List" == "java.util.ArrayList")
How can that ever be true?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900