Jordan
Jordan

Reputation: 659

How to create instance with a constructor chosen by the user?

I have been working to better understand Java's reflection tools, and am now trying to create a new instance of a class with a constructor that has been chosen by the user in a drop-down-box.

  //ask user what to name the new instance of chosen Class ( passed into this method )
            String instanceName = JOptionPane.showInputDialog(null, "Under what name would you like to store this Instance?", 
                    "Create an Instance of a Class", JOptionPane.QUESTION_MESSAGE);

            Object chosenC = JOptionPane.showInputDialog(null, "Please choose a Constructor for" + chosenClass, 
                    "Create an Instance of a Class", 3, null, getConstructors(chosenClass), JOptionPane.QUESTION_MESSAGE);

            Constructor c = (Constructor)chosenC;
            Class[] params = c.getParameterTypes(); //get the parameters of the chosen Constructor


    try {

            //create the instance with the correct constructor
            instance = c.newInstance((Object[])params); 

        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e){
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } 

Right now, I get an ArgumentTypeMismatch Exception if I select anything but the default constructor(no parameters). Am I missing something blatantly obvious?

Thank you for any help.

EDIT Thank you all for your answers.

But then how would I ask for the parameters? If I get the length of the params array, then I would have to determine what type of class each index was and ask the user to input a value in the correct form? Then how would I pass that new array into the newInstance parameter?

Upvotes: 0

Views: 1031

Answers (5)

Joeri Hendrickx
Joeri Hendrickx

Reputation: 17435

When you call newInstance on the Constructor instance, you need to pass parameters of the correct classes. You are supplying the Class objects themselves as parameters.

For instance, if your constructor is

Person(String firstName, String lastName)

You would call

new Person("John", "Doe");

Or, in reflection terms

c.newInstance("John", "Doe");

But your code is in fact doing

c.newInstance(String.class, String.class);

If you want the user to select a constructor, you will need to ask him for some parameters as well.

Upvotes: 1

Danilo Tommasina
Danilo Tommasina

Reputation: 1760

The call to:

instance = c.newInstance((Object[])params); 

here you have to pass in the arguments for the constructor and not the types that you get with the call:

Class[] params = c.getParameterTypes();

If your constructor is:

public MyConstructor( int foo, String bar ) {
//...
}

then you should pass in params as (e.g.):

Object [] params = new Object [] { 10, "someString" };

Upvotes: 1

Peter Lawrey
Peter Lawrey

Reputation: 533500

Your params need to be the arguments passed to the constructor. Your params are all Class references so unless all your parameters are Class a, Class b, Class c This won't work.

Perhaps you should allow the user to determine what the values should be.

Upvotes: 1

David Grant
David Grant

Reputation: 14223

Given a class with a constructor like so:

MyClass(String s, Long l)

Your code is actually invoking the following:

new MyClass(String.class, Long.class)

Where it should be invoking:

new MyClass("", 1L)

You need an instance of each of the constructor parameter types, but you're only passing classes. Interestingly, if you constructor only takes instances of Class, it would work, but would give unexpected results.

Upvotes: 3

sbridges
sbridges

Reputation: 25150

You are passing a Class[] to the constructor, when you want an array of instances. For example, if your constructor is Foo(String), you want to do something like

c.newInstance(new Object[] {"aString"});

What you are doing is,

c.newInstance(new Object[] {String.class});

Upvotes: 1

Related Questions