1
votes

I have this code:

Class I want to copy:

public class NormalChair extends AbstractChair {
    protected int height;
    protected String name;
    public NormalChair() {
        super();
    }

    public NormalChair(String name, int height) {
        super(name, height);
    }


    // Copy constructor - getName() and getHeight() are defined in parent class.
    public NormalChair(NormalChair chair) {
      this(chair.getName(), chair.getHeight());
    } 
}

Create some class

public Object createObj(String cls_name, String param1, int param2){ return Class.forName(cls_name).getConstructor(String.class, Integer.class).newInstance(param1, param2); }

Then I try to copy object of that class using this:

Object obj_to_copy = createObj("Classname", "name", 10);
String cls_name = obj_to_copy.getClass().getName();
Class.forName(cls_name).getConstructor(Object.class).newInstance(obj_to_copy);

And I get this error:

Exception in thread "main" java.lang.NoSuchMethodException: test.NormalChair.<init>(java.lang.Object)
    at java.lang.Class.getConstructor0(Class.java:2800)
    at java.lang.Class.getConstructor(Class.java:1708)
    at test.ProductTrader.create(ProductTrader.java:57)
    at test.Test.main(Test.java:23)

So I suppose I need to call copy constructor somehow differently than showing it's type as Object?

P.S. Also I gave this example as simplistic. But in reality I would not know which class needs to be copied before runtime, so using copy constructor should not depend only on NormalChair class.

Update:

I updated my question, to make it more clear that when I copy object, before, runtime, I won't know what class it will need to copy.

3
Maybe Class.forName(cls_name).getConstructor(NormalChair.class)? - Andrew Logvinov
Well maybe I didn't explained well. I gave simplistic example, but in reality I will not know which class I need to copy, so in constructor, I would need to use something that can change depending on class I need to copy. - Andrius
Some guy posted answer that worked, but he deleted it for some reason... The thing that worked for me was to use objc_to_copy.getClass() inside getConstructor. - Andrius
@Andrius, if the object that you want to copy is nc then nc.getClass() will give the NormalChair class - Sage
This is not the answer to your question, but I can see another problem. Your AbstractChair class apparently has height and name fields, but NormalChair is declaring duplicate fields (protected int height; protected String name;) with the same names. Although they have the same names they are not otherwise related, and they could have different values, leading to confusion and bugs. You should remove the height and name fields on class NormalChair. - Boann

3 Answers

0
votes

Java reflection for some reason matches classes and method signatures strictly. So in order to find a matching constructor, you would need to enumerate available constructors with Class.getDeclaredConstructors() and find a matching one.

I have written a small library to simplify the task, here is a method matching class from it: HavingMethodSignature.

If you're interested, here is how you create a new instance with this lib:

Object o = OpenBean.newInstance(Class.forName(cls_name));
0
votes

Why bother with a copy constructor in Java ? There is a standard way to copy an object in Java : simply clone it. If default cloning is not relevant, override the clone() method.

You simply need to write obj.clone() to get a copy.

see Java documentation of clone() for details.

0
votes

If you can assume that a copy constructor accepts an object of the same class, you can do something like:

class ObjectCopier {
    public static Object copy(Object orig) {
        Class<?> cls = orig.getClass();
        Constructor<?> con = cls.getDeclaredConstructor(cls);

        return ((con == null) ? null : con.newInstance(orig);
    }
}

(untested, so treat it as such)