Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.java.programmer > #34468 > unrolled thread
| Started by | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| First post | 2016-06-04 15:27 -0400 |
| Last post | 2016-06-06 21:18 -0400 |
| Articles | 9 on this page of 29 — 8 participants |
Back to article view | Back to comp.lang.java.programmer
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: Are you sure, Mr. Gosling? Arne Vajhøj <arne@vajhoej.dk> - 2016-06-04 15:27 -0400
Re: Are you sure, Mr. Gosling? Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-04 16:43 -0400
Re: Are you sure, Mr. Gosling? Arne Vajhøj <arne@vajhoej.dk> - 2016-06-04 18:44 -0400
Re: Are you sure, Mr. Gosling? Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-05 08:05 -0400
Re: Are you sure, Mr. Gosling? Arne Vajhøj <arne@vajhoej.dk> - 2016-06-05 08:31 -0400
Re: Are you sure, Mr. Gosling? Eric Douglas <e.d.programmer@gmail.com> - 2016-06-06 05:22 -0700
Re: Are you sure, Mr. Gosling? Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-06 09:00 -0400
Re: Are you sure, Mr. Gosling? v_borchert@despammed.com (Volker Borchert) - 2016-06-06 16:06 +0000
Re: Are you sure, Mr. Gosling? Robert Klemme <shortcutter@googlemail.com> - 2016-06-06 22:56 +0200
Re: Are you sure, Mr. Gosling? Eric Douglas <e.d.programmer@gmail.com> - 2016-06-07 05:08 -0700
Re: Are you sure, Mr. Gosling? Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-07 08:41 -0400
Re: Are you sure, Mr. Gosling? Martin Gregorie <martin@address-in-sig.invalid> - 2016-06-07 13:14 +0000
Re: Are you sure, Mr. Gosling? Eric Douglas <e.d.programmer@gmail.com> - 2016-06-07 06:30 -0700
Re: Are you sure, Mr. Gosling? Robert Klemme <shortcutter@googlemail.com> - 2016-06-07 19:10 +0200
Re: Are you sure, Mr. Gosling? Eric Douglas <e.d.programmer@gmail.com> - 2016-06-07 10:22 -0700
Re: Are you sure, Mr. Gosling? Mike Amling <mamling@chaff.us> - 2016-06-07 15:31 -0500
Re: Are you sure, Mr. Gosling? Eric Douglas <e.d.programmer@gmail.com> - 2016-06-08 06:31 -0700
Re: Are you sure, Mr. Gosling? Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-08 10:41 -0400
Re: Are you sure, Mr. Gosling? Eric Douglas <e.d.programmer@gmail.com> - 2016-06-08 10:21 -0700
Re: Are you sure, Mr. Gosling? Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-08 14:10 -0400
Re: Are you sure, Mr. Gosling? Robert Klemme <shortcutter@googlemail.com> - 2016-06-08 20:54 +0200
Re: Are you sure, Mr. Gosling? Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-08 16:36 -0400
Re: Are you sure, Mr. Gosling? Robert Klemme <shortcutter@googlemail.com> - 2016-06-08 23:11 +0200
Re: Are you sure, Mr. Gosling? Lew <lewbloch@gmail.com> - 2016-06-10 12:20 -0700
Re: Are you sure, Mr. Gosling? Robert Klemme <shortcutter@googlemail.com> - 2016-06-14 19:10 +0200
Re: Are you sure, Mr. Gosling? Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-07 17:12 -0400
Re: Are you sure, Mr. Gosling? Robert Klemme <shortcutter@googlemail.com> - 2016-06-07 23:25 +0200
Re: Are you sure, Mr. Gosling? Arne Vajhøj <arne@vajhoej.dk> - 2016-06-07 17:33 -0400
Re: Are you sure, Mr. Gosling? Arne Vajhøj <arne@vajhoej.dk> - 2016-06-06 21:18 -0400
Page 2 of 2 — ← Prev page 1 [2]
| From | Robert Klemme <shortcutter@googlemail.com> |
|---|---|
| Date | 2016-06-08 20:54 +0200 |
| Message-ID | <drr804FhojnU1@mid.individual.net> |
| In reply to | #34564 |
On 08.06.2016 15:31, Eric Douglas wrote:
> On Tuesday, June 7, 2016 at 4:30:34 PM UTC-4, Mike Amling wrote:
> If both methods return the same object, my understanding is the copy
> constructor just looks cleaner if you have a lot of variables you want
> as default values and the clone method will copy those by default so
> should look cleaner if you have a lot of variables you want copied.
That does not make sense: if you want to copy state then you do not want
the default values. You want the actual values from the object.
Actually, cloning and copying should preserve observable state.
And if you have some state that is caching something and you want the
cache (say a Map) to be empty in the copy then you need to assign the
member with a freshly created instance in both cases. So there is no
difference in amount of assignments needed.
It may even be the other way round: clone() might require less
assignments if there is state in immutable objects whose references can
be shared.
> A copy constructor by default creates an instance of the current
> class. A clone method by default creates an instance of Object,
NO! Please read what is written in this thread or the documentation of
clone().
> so
> either the clone method of the Cloneable class must cast super.clone()
> to it's own class, or everything that calls it's clone method must cast
> the result.
Yes and yes. Note that the API was defined before generics, that's why
it is the way it is.
> Defaults from clone() to consider (if we don't want these, we either
> need to specify the alternative in the copy constructor, or replace in
> the clone method on the new instance returned from super.clone()):
> Immutable objects get copied by value, bucket objects get copied by
> reference.
This is wrong. Objects ("reference types") are copied by reference by
Object.clone() - regardless of whether they are mutable or not. Only
primitive types are copied by value.
Cheers
robert
--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
[toc] | [prev] | [next] | [standalone]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2016-06-08 16:36 -0400 |
| Message-ID | <nj9vlk$7t2$1@dont-email.me> |
| In reply to | #34574 |
On 6/8/2016 2:54 PM, Robert Klemme wrote:
> [...]
> This is wrong. Objects ("reference types") are copied by reference by
> Object.clone() - regardless of whether they are mutable or not. Only
> primitive types are copied by value.
It's always seemed to me that the clearest way to think about
this is to say *everything* is copied by value. The values may be
primitives or they may be references, but those values are copied.
The objects to which those references refer (if non-null) are
independent of the thing being copied, and are not even touched by
Object.clone() -- which is why a clone() override that wants an
independent referred-to object must take additional steps.
This viewpoint ("references are just like primitives") also
seems to clarify how method/constructor parameters are initialized
from argument expressions.
--
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM
[toc] | [prev] | [next] | [standalone]
| From | Robert Klemme <shortcutter@googlemail.com> |
|---|---|
| Date | 2016-06-08 23:11 +0200 |
| Message-ID | <drrg0uFjd8nU1@mid.individual.net> |
| In reply to | #34575 |
On 08.06.2016 22:36, Eric Sosman wrote:
> On 6/8/2016 2:54 PM, Robert Klemme wrote:
>> [...]
>> This is wrong. Objects ("reference types") are copied by reference by
>> Object.clone() - regardless of whether they are mutable or not. Only
>> primitive types are copied by value.
>
> It's always seemed to me that the clearest way to think about
> this is to say *everything* is copied by value. The values may be
> primitives or they may be references, but those values are copied.
This is also correct and there is some merit in presenting it that way.
I just believe that deviates from the usual presentation and thus
might cause confusion.
I think using terms like "copy by value", "copy by reference" etc. helps
describe different scenarios. Of course, underneath always "something"
is copied. But it is always something different. And different terms
help distinguish that.
Here's a nice summary of value semantics:
https://courses.cs.washington.edu/courses/cse505/99au/imperative/parameters.html
Kind regards
robert
--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
[toc] | [prev] | [next] | [standalone]
| From | Lew <lewbloch@gmail.com> |
|---|---|
| Date | 2016-06-10 12:20 -0700 |
| Message-ID | <60f13013-4df5-453d-bf62-78283e57e79b@googlegroups.com> |
| In reply to | #34574 |
On Wednesday, June 8, 2016 at 11:55:13 AM UTC-7, Robert Klemme wrote:
> On 08.06.2016 15:31, Eric Douglas wrote:
> > On Tuesday, June 7, 2016 at 4:30:34 PM UTC-4, Mike Amling wrote:
>
> > If both methods return the same object, my understanding is the copy
> > constructor just looks cleaner if you have a lot of variables you want
> > as default values and the clone method will copy those by default so
> > should look cleaner if you have a lot of variables you want copied.
>
> That does not make sense: if you want to copy state then you do not want
> the default values. You want the actual values from the object.
> Actually, cloning and copying should preserve observable state.
>
> And if you have some state that is caching something and you want the
> cache (say a Map) to be empty in the copy then you need to assign the
> member with a freshly created instance in both cases. So there is no
> difference in amount of assignments needed.
>
> It may even be the other way round: clone() might require less
> assignments if there is state in immutable objects whose references can
> be shared.
>
> > A copy constructor by default creates an instance of the current
> > class. A clone method by default creates an instance of Object,
>
> NO! Please read what is written in this thread or the documentation of
> clone().
>
> > so
> > either the clone method of the Cloneable class must cast super.clone()
> > to it's own class, or everything that calls it's clone method must cast
> > the result.
>
> Yes and yes. Note that the API was defined before generics, that's why
> it is the way it is.
>
> > Defaults from clone() to consider (if we don't want these, we either
> > need to specify the alternative in the copy constructor, or replace in
> > the clone method on the new instance returned from super.clone()):
> > Immutable objects get copied by value, bucket objects get copied by
> > reference.
>
> This is wrong. Objects ("reference types") are copied by reference by
> Object.clone() - regardless of whether they are mutable or not. Only
> primitive types are copied by value.
That isn't correct. References are copied, by default, but they are copied by value. When 'clone' is overridden appropriately, those references are dereferenced, and the values to which they point are copied. However you look at it, it is values that are copied - either pointer values or primitive values.
Copy-by-reference means that the original reference will point to the new object, which is not what we want nor what 'clone' does.
This is similar to the logic that proves that method arguments in Java are always passed by value. Java doesn't actually have references, as C++ programmers and others understand them. It has pointers.
--
Lew
[toc] | [prev] | [next] | [standalone]
| From | Robert Klemme <shortcutter@googlemail.com> |
|---|---|
| Date | 2016-06-14 19:10 +0200 |
| Message-ID | <dsas48Fm2pvU1@mid.individual.net> |
| In reply to | #34594 |
On 10.06.2016 21:20, Lew wrote:
> On Wednesday, June 8, 2016 at 11:55:13 AM UTC-7, Robert Klemme wrote:
>> On 08.06.2016 15:31, Eric Douglas wrote:
>>> Defaults from clone() to consider (if we don't want these, we either
>>> need to specify the alternative in the copy constructor, or replace in
>>> the clone method on the new instance returned from super.clone()):
>>> Immutable objects get copied by value, bucket objects get copied by
>>> reference.
>>
>> This is wrong. Objects ("reference types") are copied by reference by
>> Object.clone() - regardless of whether they are mutable or not. Only
>> primitive types are copied by value.
>
> That isn't correct. References are copied, by default, but they are
> copied by value. When 'clone' is overridden appropriately, those
> references are dereferenced, and the values to which they point are
> copied. However you look at it, it is values that are copied - either
> pointer values or primitive values.
Yes, references (pointers) are copied by value, i.e. there is a new
object that has a pointer to the same object. That is the default
behavior of clone(). This is different from what Eric had written (see
above) and which prompted my response.
Now, of course, if you override it typically you would retain some
references (e.g. to immutable objects) and provide new values for others
(e.g. to collections), typically by creating a new object one way or
another (i.e. invoking clone(), a constructor, a factory method or
something else) or using a default value (e.g. null).
> Copy-by-reference means that the original reference will point to the
> new object, which is not what we want nor what 'clone' does.
I am not sure. Now that we have talked about it so much I am not sure
any more that "copy by reference" is actually properly defined. It
seems a parallel construction to "call by reference" but that describes
another situation, namely a non-copy of a value. You could describe
this as copying an immutable pointer (in C++ you cannot change what a
reference points to, as opposed to a pointer).
> This is similar to the logic that proves that method arguments in
> Java are always passed by value. Java doesn't actually have
> references, as C++ programmers and others understand them. It has
> pointers.
Well, underneath all are pointers (to memory addresses). In C++ the
difference is that you can change a pointer (i.e. where it points to)
but not a reference. In that sense references in Java are really pointers.
Kind regards
robert
--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
[toc] | [prev] | [next] | [standalone]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2016-06-07 17:12 -0400 |
| Message-ID | <nj7dbg$shs$1@dont-email.me> |
| In reply to | #34541 |
On 6/7/2016 1:22 PM, Eric Douglas wrote:
> On Tuesday, June 7, 2016 at 1:10:36 PM UTC-4, Robert Klemme wrote:
>> That sounds more like a use case for clone() to me as it seems to stress
>> that the original type is preserved. It really depends on the usage.
>
> Maybe I'm getting confused then. I thought clone() sounded wrong because it should return an instance of that class, so if you extend the class and call super.clone it gets an instance of the base class? If your extended class needs to return an instance of itself, which needs to copy all the same values as the super class plus a few more...
>
> example:
> public class BaseClass{
> private Obj1 obj1;
> private Obj2 obj2;
> public BaseClass(final BaseClass copyMe) {
> setObj1(copyMe.getObj1());
> setObj2(copyMe.getObj2());
Aside: Don't call overridable methods from a constructor.
> }
> public Obj1 getObj1(){
> return obj1;
> }
> public Obj2 getObj2(){
> return obj2;
> }
> public void setObj1(final Obj1 newObj){
> obj1=newObj;
> }
> public void setObj2(final Obj2 newObj){
> obj2=newObj;
> }
> }
> public class ExtendedClass extends BaseClass{
> private Obj3 obj3;
> public ExtendedClass(final ExtendedClass copyMe){
> super(copyMe);
> setObj3(copyMe.getObj3());
> }
> public Obj3 getObj3(){
> return obj3;
> }
> public void setObj3(final Obj3 newObj){
> obj3=newObj;
> }
> }
>
> How would you do the clone()?
It depends on whether the obj{1,2,3} instances should be shared
by the original object and its clone, or whether they need to be
independent. (Bloch offers an example of a stack implementation with
an internal array; if you clone the stack object without also cloning
the array, both stacks will share the same array ...)
In the first case (obj{1,2,3} are shareable), all you need do
is make both classes Cloneable:
public class BaseClass implements Cloneable {
// ...
@Override
public // or protected, if you prefer
Object clone() throws CloneNotsupportedException {
return super.clone();
}
// ...
}
public class ExtendedClass extends BaseClass {
// ...
@Override
public Object clone() throws CloneNotsupportedException {
return super.clone();
}
}
The clone() calls will percolate all the way up to Object's clone(),
which will check that the originating object implements Cloneable and
them return a field-for-field copy of that originating object, with the
originating object's class. (In this instance the intervening clone()
calls just pass that object along, so the class of the eventual object
is BaseClass or ExtendedClass, depending on where things started.)
But if one or more of obj{1,2,3} is unshareable, the clone() methods
must provide suitable substitutes: clones or copies of the unshareable
objects. Let's suppose the odd-numbered fields must be unique; then
you'd have something like
public class BaseClass implements Cloneable {
// ...
@Override
public Object clone() throws CloneNotsupportedException {
BaseClass cloned = (BaseClass) super.clone();
cloned.obj1 = independentCopyOf(obj1);
// obj2 can be shared; just leave it alone.
return cloned;
}
// ...
}
public class ExtendedClass extends BaseClass {
// ...
@Override
public Object clone() throws CloneNotsupportedException {
ExtendedClass cloned = (ExtendedClass) super.clone();
cloned.obj3 = independentCopyOf(obj3);
return cloned;
}
// ...
}
You'll see I'm waving my hands a bit with that independentCopyOf()
fiction. It might be `cloned.obj1 = obj1.clone()' -- in which case the
fields should probably be Cloneable's rather than Object's -- or it
might be an invocation of a copy constructor -- in which case, again,
the fields should be more specific about their classes so you can do
`cloned.obj1 = new Class1(obj1)' and so on. Or it might be something
else altogether, depending on what you mean by a "copy" of your object.
Finally, the clone() methods I've shown simply pass along the
object created by Object's clone(), whose class will be the same as
that of the ultimate "leaf" class of the clone operation. That's a
fairly normal state of affairs, but it is *not* enforced, nor even
required. It is entirely possible (though perverse) that the clone()
method applied to a Woozle object might instead return a Grizzle,
or even a String. Or even null. You have to know what to expect
from the chain of superclasses.
--
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM
[toc] | [prev] | [next] | [standalone]
| From | Robert Klemme <shortcutter@googlemail.com> |
|---|---|
| Date | 2016-06-07 23:25 +0200 |
| Message-ID | <droseuF3h3gU1@mid.individual.net> |
| In reply to | #34547 |
On 07.06.2016 23:12, Eric Sosman wrote:
> On 6/7/2016 1:22 PM, Eric Douglas wrote:
>> On Tuesday, June 7, 2016 at 1:10:36 PM UTC-4, Robert Klemme wrote:
>>> That sounds more like a use case for clone() to me as it seems to stress
>>> that the original type is preserved. It really depends on the usage.
>>
>> Maybe I'm getting confused then. I thought clone() sounded wrong
>> because it should return an instance of that class, so if you extend
>> the class and call super.clone it gets an instance of the base class?
>> If your extended class needs to return an instance of itself, which
>> needs to copy all the same values as the super class plus a few more...
The usual implementation invokes super.clone() exactly as Eric has shown
in this posting. And Object.clone() makes sure the type of the instance
is the same as the receiver of the method.
> The clone() calls will percolate all the way up to Object's clone(),
> which will check that the originating object implements Cloneable and
> them return a field-for-field copy of that originating object, with the
> originating object's class. (In this instance the intervening clone()
> calls just pass that object along, so the class of the eventual object
> is BaseClass or ExtendedClass, depending on where things started.)
>
> But if one or more of obj{1,2,3} is unshareable, the clone() methods
> must provide suitable substitutes: clones or copies of the unshareable
> objects. Let's suppose the odd-numbered fields must be unique; then
> you'd have something like
>
> public class BaseClass implements Cloneable {
> // ...
> @Override
> public Object clone() throws CloneNotsupportedException {
> BaseClass cloned = (BaseClass) super.clone();
> cloned.obj1 = independentCopyOf(obj1);
> // obj2 can be shared; just leave it alone.
> return cloned;
> }
> // ...
> }
>
> public class ExtendedClass extends BaseClass {
> // ...
> @Override
> public Object clone() throws CloneNotsupportedException {
> ExtendedClass cloned = (ExtendedClass) super.clone();
> cloned.obj3 = independentCopyOf(obj3);
> return cloned;
> }
> // ...
> }
One note though: I would catch CloneNotsupportedException in the
BaseClass implementation of clone() because the exception cannot be
thrown. It just pollutes the signature of clone() unnecessarily.
> Finally, the clone() methods I've shown simply pass along the
> object created by Object's clone(), whose class will be the same as
> that of the ultimate "leaf" class of the clone operation. That's a
> fairly normal state of affairs, but it is *not* enforced, nor even
> required. It is entirely possible (though perverse) that the clone()
> method applied to a Woozle object might instead return a Grizzle,
> or even a String. Or even null. You have to know what to expect
> from the chain of superclasses.
Any reasonable implementation would _not_ deviate from the convention to
propagate clone() calls in the way you have shown. Doing that opens the
box of Pandora _and_ the Gates of Hell (and I am not talking about Bill).
Kind regards
robert
--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
[toc] | [prev] | [next] | [standalone]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2016-06-07 17:33 -0400 |
| Message-ID | <nj7eio$7nu$1@gioia.aioe.org> |
| In reply to | #34541 |
On 6/7/2016 1:22 PM, Eric Douglas wrote:
> On Tuesday, June 7, 2016 at 1:10:36 PM UTC-4, Robert Klemme wrote:
>> That sounds more like a use case for clone() to me as it seems to
>> stress that the original type is preserved. It really depends on
>> the usage.
>
> Maybe I'm getting confused then. I thought clone() sounded wrong
> because it should return an instance of that class, so if you extend
> the class and call super.clone it gets an instance of the base class?
> If your extended class needs to return an instance of itself, which
> needs to copy all the same values as the super class plus a few
> more...
You have already gotten several examples.
I will just add a ref to the docs:
https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#clone--
<quote>
Creates and returns a copy of this object. The precise meaning of "copy"
may depend on the class of the object. The general intent is that, for
any object x, the expression:
x.clone() != x
will be true, and that the expression:
x.clone().getClass() == x.getClass()
will be true, but these are not absolute requirements. While it is
typically the case that:
x.clone().equals(x)
will be true, this is not an absolute requirement.
By convention, the returned object should be obtained by calling
super.clone. If a class and all of its superclasses (except Object) obey
this convention, it will be the case that x.clone().getClass() ==
x.getClass().
By convention, the object returned by this method should be independent
of this object (which is being cloned). To achieve this independence, it
may be necessary to modify one or more fields of the object returned by
super.clone before returning it. Typically, this means copying any
mutable objects that comprise the internal "deep structure" of the
object being cloned and replacing the references to these objects with
references to the copies. If a class contains only primitive fields or
references to immutable objects, then it is usually the case that no
fields in the object returned by super.clone need to be modified.
The method clone for class Object performs a specific cloning operation.
First, if the class of this object does not implement the interface
Cloneable, then a CloneNotSupportedException is thrown. Note that all
arrays are considered to implement the interface Cloneable and that the
return type of the clone method of an array type T[] is T[] where T is
any reference or primitive type. Otherwise, this method creates a new
instance of the class of this object and initializes all its fields with
exactly the contents of the corresponding fields of this object, as if
by assignment; the contents of the fields are not themselves cloned.
Thus, this method performs a "shallow copy" of this object, not a "deep
copy" operation.
The class Object does not itself implement the interface Cloneable, so
calling the clone method on an object whose class is Object will result
in throwing an exception at run time.
</quote>
Which pretty well explains why sub classing is actually a thing that
clone handles very well.
Arne
[toc] | [prev] | [next] | [standalone]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2016-06-06 21:18 -0400 |
| Message-ID | <nj57cr$hl0$1@gioia.aioe.org> |
| In reply to | #34492 |
On 6/6/2016 8:22 AM, Eric Douglas wrote: > On Sunday, June 5, 2016 at 8:05:40 AM UTC-4, Eric Sosman wrote: >> Gosling et al. vote for Cloneable: >> Bloch votes against it: > > So what's the verdict, I have a class with a copy constructor, should I change it to be Cloneable? Not necessarily. It is your choice. I would prefer Cloneable. Not because it is better in some objective design sense, but just because it is more common in Java, so future maintainers of the code will easily understand what the intention was. But you != me, so ... Arne
[toc] | [prev] | [standalone]
Page 2 of 2 — ← Prev page 1 [2]
Back to top | Article view | comp.lang.java.programmer
csiph-web