2

Let's say I have an object called myCar that is an instance of Car.

myCar = new Car();

How would I do to create a new instance of that class based on the object? Let's say that I don't know which class myCar was created from.

otherObject = new myCar.getClass()(); // Just do demonstrate what I mean (I know this doesn't work)

UPDATE

public class MyClass {
    public MyClass(int x, int y, Team team) { }
    public MyClass() { }
}

Object arg = new Object[] {2, 2, Game.team[0]};

try {
    Constructor ctor = assignedObject.getClass().getDeclaredConstructor(int.class, int.class, Team.class);
    ctor.setAccessible(true);
    GameObject obj = (GameObject) ctor.newInstance(arg);

} catch (InstantiationException x) {
    x.printStackTrace();
} catch (IllegalAccessException x) {
    x.printStackTrace();
} catch (InvocationTargetException x) {
    x.printStackTrace();
} catch (NoSuchMethodException x) {
    x.printStackTrace();
}

I get the following error:

java.lang.IllegalArgumentException: wrong number of arguments

getDeclaredConstructor() works and finds my constructor with three args, but newInstance(arg) won't work for some reason, it says "wrong number of arguments". Any idea why?

lawls
  • 1,498
  • 3
  • 19
  • 34
  • This should help, also: http://stackoverflow.com/questions/7698237/whats-the-proper-way-to-use-reflection-to-instantiate-objects-of-unknown-classe – laminatefish Aug 14 '13 at 20:10

3 Answers3

16

With reflection

otherObject = myCar.getClass().newInstance();

Assuming your class has a default constructor. You can do more advanced operations with non default (empty) constructors

Constructor[] constructors = myCar.getClass().getConstructors();

And choose the one you want.

Read through this for more details about Java's Reflection capabilities.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • Thank you, is there any way I can pass in parameters to the constructor? – lawls Aug 14 '13 at 20:13
  • @lawls That is a more advanced topic, [here's](http://docs.oracle.com/javase/tutorial/reflect/member/ctorInstance.html) how. You need to pass arguments to the [`newInstance()`](http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Constructor.html#newInstance(java.lang.Object...)) method of the `Constructor` class, if and only if that constructor accepts those arguments. – Sotirios Delimanolis Aug 14 '13 at 20:14
  • It says I have to pass an array with the arguments. Let's say I have two arguments, a string and an int. How would I create that array with different types? Thanks. – lawls Aug 14 '13 at 20:31
  • Please take a look at my updated question. I have provided my code plus the error I'm getting. Do you know what seems to be the problem? Thank you. – lawls Aug 14 '13 at 20:54
  • @lawls I was wrong about how to call it. Use `(MyClass) ctor.newInstance(2, 2, Game.team[0]);` The method expects a vararg parameter, not an `Object[]`. – Sotirios Delimanolis Aug 14 '13 at 21:19
  • @lawls No problem, sorry for confusion. I couldn't understand why for a moment lol. Good luck! – Sotirios Delimanolis Aug 14 '13 at 21:22
  • @dantuch From the method side it is, but if you pass an `Object[]` to a method expecting a vararg, it'll be considered as one element in the first index position of that array. – Sotirios Delimanolis Aug 14 '13 at 21:28
  • @SotiriosDelimanolis show some example proving it. I heard something similar before, but right now I've written simple code that works just fine: `public static void main(String[] args) throws Exception { Object[] objects = new Object[] { "foo", "bar" }; DupaReflect.foo(new Object()); }` & `private static void foo(Object... objects) { for (Object object : objects) { System.out.println(object); } }` it prints elements of `Object[]` as `foo bar`, not as something like `java.lang.Object@1bab50a`... – dantuch Aug 14 '13 at 21:53
  • 1
    @SotiriosDelimanolis Ah, now I remeber - array of primitives will not work, as it cannot be autoboxed to array of wrappers http://stackoverflow.com/a/2926653/575659 #3. But when it comes to Objects it does not matter if it is explicit vararg or array of them. – dantuch Aug 14 '13 at 21:58
  • @dantuch You can edit my question with that info if you want. Or we just leave it in here. Good find. – Sotirios Delimanolis Aug 14 '13 at 21:59
0

Through reflection. Use this:

myCar.getClass().newInstance();
Kuldeep Jain
  • 8,409
  • 8
  • 48
  • 73
0

Regarding your UPDATE/error - look here:

public class DupaReflect {

    private String name;
    private int id;

    private DupaReflect(String name, int id) {
        super();
        this.name = name;
        this.id = id;
    }

    @Override
    public String toString() {
        return "DupaReflect [name=" + name + ", id=" + id + "]";
    }

    public static void main(String[] args) throws Exception {
        Object[] objects = new Object[] { "asd", 1 };
        DupaReflect dupa = DupaReflect.class.getDeclaredConstructor(String.class, int.class).newInstance(objects);
        System.out.println(dupa);
    }

}

This works and produces desired output. DupaReflect [name=asd, id=1]

Object[] objects = new Object[]{"asd", 1}; - that's the reason why my code works and yours does not.

In your code you have:

Object arg = new Object[] {2, 2, Game.team[0]};

Object[] is indeed type of Object in java, but this changes 3-element array of some objects into single object being that array. So you try to create a new object not with 3 arguments, but with 1, thus the exception is thrown

SOLUTION: Declare your Object arg as Object[] args and all should work.

dantuch
  • 9,123
  • 6
  • 45
  • 68