-4

Note: I'm aware of this question: Why doesn't Java have a copy constructor?. This question is slightly diffrent.

I'm know that the following snippet only creates a new reference to an object existing somewhere:

MyClass obj = new MyClass();
MyClass copy = obj;

But why Java wouldn't provide a default copy-constructor in the following case:

MyClass obj = new MyClass();
MyClass copy = new MyClass(obj);

I believe the implicit copy construtor could do something simillar to C++, i.e. call copy constructor on each of the members. This would result in a deep-copy of the object, presuming that all classes which manage resources have correctly implemented their copy contructors.

Adding such feature should be backward compatible also, because now the second snippet wouldn't compile without explicit copy contructor for the class.

So, to make my question more precise:

  • Is there anything preventing Java from creating implicit copy constructor, which would call copy constructor on all members?
  • Would adding implicit copy constructor now possibly break any existing program?
tryman
  • 3,233
  • 1
  • 12
  • 23
Yksisarvinen
  • 18,008
  • 2
  • 24
  • 52

2 Answers2

3

Is there anything preventing Java from creating implicit copy constructor, which would call copy constructor on all members?

Mainly the fact that this isn't obviously what it should do.

Maybe you want a deep copy in this case; maybe you want a shallow copy in that case; maybe you don't want instances to be copied at all in another case; maybe you want a particular class' fields to be copied in a mixture of these ways.

Additionally, adding this constructor is another method: in environments where the number of methods is important (e.g. Android's 64k Dex limit), you're paying for stuff you don't want.

Better to allow you to do it if you need it, by making it explicit.


But what stops Java from having this?

Given that you can manually define a copy constructor, it is clearly technically feasible to have them added automatically.

I suggest that a reason you couldn't is that there no language mechanism for "removing" the constructor for classes that you don't want to be copied.

It's easy to indicate that you don't want a default ctor: just define your own ctor, with any signature. But you couldn't do the same with a default copy ctor: by definition, a copy ctor will only ever have the signature YourClass(YourClass instance); so you couldn't require, say, that you define an explicit copy ctor which throws, because then you have changed a compile-time error (no such ctor exists) to a runtime error (it exists, but threw).

So then you have to start inventing extra mechanisms to remove the constructor - say, a special annotation. But this then requires changes to tooling to support it.

It's not impossible in the absolute sense - but it would require a lot of work to change the language to add a feature which can be implemented within the existing language.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • I'd assume if someone needs a shallow copy of a member for some reason, this would be a valid reason to write your own implementation of copy constructor. But the point about method limit is very reasonable, I didn't know about existance of such limits. Thank you. – Yksisarvinen Jan 19 '19 at 14:24
  • 1
    Java [doesn't need it](https://stackoverflow.com/a/827821/5420570), and it's not free (which could break something sensitive to it not being free). Those are indeed good reasons not to provide it. – T.J. Crowder Jan 19 '19 at 14:27
  • 2
    @Yksisarvinen the point is not so much that you *couldn't* override the copy constructor if it defaulted to deep copying; I am questioning whether that is the correct default. I ran some analysis on Google's code, and found that the number of classes with copy constructors is small - really small - *well* under 1%. Whilst this is merely one codebase that might have particular stylistic reasons for it being that low (e.g. this includes generated classes like protos, which have no copy ctor), it still points to a lack of value in having copy constructors by default, of whatever variety. – Andy Turner Jan 19 '19 at 16:37
  • 1
    @Yksisarvinen (and a disproportionate burden to remove the copy constructors for classes which never need to be copied). – Andy Turner Jan 19 '19 at 16:39
  • 2
    @AndyTurner and then, amongst this small fraction of classes having a copy constructor, there are classes which *shouldn’t* have it, most prominently, `java.lang.String`… – Holger Jan 29 '19 at 17:53
2

But it does. It's the method called clone() and is implemented in the class Object.

So what you want to do, can be achieved with the following:

MyClass obj = new MyClass(); 
MyClass copy = (MyClass) obj.clone();
Soutzikevich
  • 991
  • 3
  • 13
  • 29
  • You might want to address the two boldfaced, bullet-pointed questions in the question. – T.J. Crowder Jan 19 '19 at 14:09
  • I wouldn't say this is "implicit". It requires us to provide implementation for `clone()` method instead of copy contructor, but the implementation is almost the same. – Yksisarvinen Jan 19 '19 at 14:13
  • 4
    You might also want to point out the issues with `clone () `, as given in Effective Java. – daniu Jan 19 '19 at 14:14