3

Suppose you have a class with this constructor:

public SomeObj(int x, int y) {
    this.x = x;
    this.y = y;
}

All good. But now if you want to clone the object, I want a constructor to accept one argument with an object from that type, so inside the constructor all (necessary) fields can be copied.

public SomeObj(SomeObj objectToClone) { ... }

But now which of the following two ways is better? What are the advantages and disadvantages (performance (byte code), readability...)?

// 1
public SomeObj(SomeObj objectToClone) {
    this.x = objectToClone.x;
    this.y = objectToClone.y;
}

// 2
public SomeObj(SomeObj objectToClone) {
    this(objectToClone.x, objectToClone.y);
}

6 Answers 6

13

I would go with the latter, personally.

Where possible, I try to make exactly one constructor have a "real" body, and make all others delegate to it. That's not always possible - in particular, different constructors may need to delegate to different superconstructors - but it's nice knowing there's one place you can put extra initialization, logging, breakpoints etc which will always get hit.

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

2 Comments

+1: Having one "real" constructor all the others call means the functionality will be consistent between constructors. Having different code in different constructors can be a nightmare.
Although it's just a vision on this subject, I would like to accept this answer (even though you already have loads of points and medals). Because this vision gives me a clear view on this one.
3

Number 2 is better. Why? because you are no longer repeating yourself, setting a member in two different constructors.

There is no performance hit really, unless the miniscule extra indirection of calling this() is going to affect you (and i doubt you can even measure this difference accurately).

1 Comment

@Mudu: i m not sure if the compiler inlines it, but yea, it might!
2

If you use the second option, you don't have to change public SomeObj(SomeObj objectToClone) every time you change the implementation of public SomeObj(int x, int y). So it is better as it allows you to avoid duplicating code.

Comments

1

It's not C++. Override .clone() method from Object class for copy objects. It's true way

3 Comments

+1 for the option. But it does not vote for one of the options. From clone, I'd personally invoke the constructor instead of copying the fields again.
Isn't clone() traditionally used for deep copying? I think it should be overridden in that case only.
Okay, but the question is not about the clone thing — that was just an example. It's about passing this(...) to another constructor.
1

The latter does not build anymore as soon as you add another parameter, let's say z. If you'd take the first approach, you might just forget to copy z. It still builds, but doesn't work properly.

2 Comments

Don't build but the compiler give you and error, but the first.... builds but it doesn't work if you add another parameter.
That is what I wanted to point out. I tried to express myself more clearly.
0
// 1
public SomeObj(SomeObj objectToClone) {
    this.x = objectToClone.x;
    this.y = objectToClone.y;
}

is better.

Your second option would require you to update your constructor each time you add a new parameter. Also, if you have to call that in 100 places with 100 properties to list in each constructor, it's obvious it starts loosing readability.

I can't understand why you would like to pass multiple properties of the same object as parameter instead of passing the object. There's no reason for that.

Compare these two:

public SomeObj(SomeObj objectToClone) {
    this.x = objectToClone.x;
    this.y = objectToClone.y;
    this.z = objectToClone.z;
    this.p = objectToClone.p;
    this.s = objectToClone.s;
    this.a = objectToClone.a;
    this.b = objectToClone.b;
    }

and then call SomeObj(obj) 10 times in your code.

versus SomeObj(obj.x,obj.y,obj.z,obj.p,obj.s,obj.t,obj.a,obj.b); 10 times in your code

Also, with the second option you have no guarantee that the parameters passed are what you want, so you could get something like this: SomeObj(obj.x,obj.y,obj2.z,obj3.p,0,0,-1,null);

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.