3

After a long day of searching, I still can't figure out how I can instanciate a new object from a selfmade class, if the constructor takes non-primitive arguments. Now I start doubting if this is possible at all?!

In the Documentation of Reflection, they only talk about primitive types (like int, float, boolean, etc.) as far as I saw. And all other information/website/workshop/example I found also just consider primitive types to find the constructor and instanciate a new instance.

So what I want to do is the following (broken down scenario):

Suppose I got a class called MyStupidClass. Another class (let's name it MyUsingClass) takes a MyStupidClass object as argument in the constructor. Now in my main application, I want to be able to load the MyUsingClass class and instanciate an object out of the constructor.

This is what I found out about "using Reflection" so far:

With empty constructor:

//the MyUsingClass:
public class MyUsingClass {

   //the public (empty) constructor
   public MyUsingClass() {
      ...
   }
}

In the main application, I would now do something like:

//get the reflection of the MyUsingClass
Class<?> myUsingClassClass = Class.forName("MyUsingClass");
//get the constructor [I use getConstructor() instead of getConstructors(...) here as I know there is only one]
Constructor<?> myUsingClassConstr = myUsingClassClass.getConstructor();
//instanciate the object through the constructor
Object myInstance = myUsingClassConstr.newInstance(null);

Now if I would use some primitive types in MyUsingClass, it would look something like:

//the MyUsingClass:
public class MyUsingClass {

   //the public (primitive-only) constructor
   public MyUsingClass(String a, int b) {
      ...
   }
}

In the main application, the last line would change to something like:

//instanciate the object through the constructor
Object myInstance = myUsingClassConstr.newInstance(new Object[]{new String("abc"), new Integer(5)});

So far no problems (there might be some small errors in the code above as it is only a broken down example...) Now the clue question is, how can I create myInstance, if the MyUsingClass looks something like:

//the MyUsingClass:
public class MyUsingClass {

   //the public (primitive-only) constructor
   public MyUsingClass(String a, int b, MyStupidObject toto) {
      ...
   }
}

? Any help would be appreciated! Thank you already for reading through my question!

greets sv

2
  • 1
    String is not a primitive. Did you try to do the same for MyStupidObject as you did for String? Commented Nov 28, 2010 at 19:53
  • The newInstance method takes in an array of Objects. There is nothing in the JavaDoc API that says the parameters must be wrapped primitive types. It just says that they will be unwrapped as needed. Have you tried something like: nObject myInstance = myUsingClassConstr.newInstance(new Object[]{new String("abc"), new Integer(5), new MyStupidObject()});? If so, and it did not work, what was the exception? Commented Nov 28, 2010 at 20:02

3 Answers 3

13

No problem. Many years ago, I spent a lot of time for this thing too.

  1. You can use Class.newInstance() only if you call default constructor.
  2. In all other cases you have to first find appropriate constructor by calling getConstructor() and the call its newInstance().
  3. When you call getConstructor() use int.class, long.class, boolean.class, etc for primitives. If your class Foo has constructor Foo(int p) you have to say

    Constructor c = Foo.class.getConstructor(int.class);

  4. Once you have constructor call it using newInstance():

    c.newInstance(12345);

For multi-arguments constructor, say something like:

`c.newInstance(new Object[] {12345, "foo", true})`

Pay attention that we have a luck of autoboxing since java 5. For versions prior to 5, we had to use more verbose syntax:

`c.newInstance(new Object[] {new Integer(12345), "foo", new Boolean(true)})`

i.e. we used int.class to locate constructor and Integer type to call it.

I hope this helps.

Sign up to request clarification or add additional context in comments.

1 Comment

Notice that we also have the luck of variable arguments - no need for that object array. c.newInstace(12345, "foo", true)
1

The same way you called the constructor for the other types:

Object myInstance = myUsingClassConstr.newInstance(new Object[] {
    new String("abc"),
    new Integer(5),
    new MyStupidObject()
});

From the Constructor.newInstance documentation:

Uses the constructor represented by this Constructor object to create and initialize a new instance of the constructor's declaring class, with the specified initialization parameters. Individual parameters are automatically unwrapped to match primitive formal parameters, and both primitive and reference parameters are subject to method invocation conversions as necessary.

Reference types are specifically listed there, and require no special treatment.

1 Comment

Notice how the .newInstance(Object... args) has variable args. You can skip the array and use autoboxing for the Integer: .newInstance("abc", 5, new MyStupidObject())
0

Ok, this (all the answers) helped me alot. It's working now, at least at first glance. Will need some further testing, but I hope I well get through this alone now!

Thank you very much...

[They could be more specific on this topic in the specifications, though]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.