commons-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Ben Speakmon (JIRA)" <j...@apache.org>
Subject [jira] Commented: (LANG-354) Implementation of a CloneBuilder Class
Date Tue, 13 Nov 2007 00:03:50 GMT

    [ https://issues.apache.org/jira/browse/LANG-354?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12541995
] 

Ben Speakmon commented on LANG-354:
-----------------------------------

A neat idea. Problems:

1) I don't like calling it CloneBuilder. Cloning is associated with java.lang.Cloneable and
Object.clone(), which follow a rather hairy extralinguistic procedure for making clones. It
implies a whole bunch of weird conditions and contracts (see Item 10 in Effective Java). Something
like ObjectCopier, maybe?
2) Some objects (singletons, system classes, etc.) aren't meant to have multiple instances,
and the designers usually go to lengths to stop you (final, private constructor, etc.). This
won't work for those classes.
3) Most seriously, this breaks for objects with non-primitive fields. Consider:

        Person joe = new Person();
        joe.setName("Joe");
        joe.setAge(28);
        ArrayList joeKids = new ArrayList();
        joeKids.add("Jack");
        joeKids.add("Jill");
        joe.setDependents(joeKids);

        Person joe2 = (Person) CloneBuilder.reflectionClone(joe);

        joeKids.remove("Jill");    // YOU WERE ADOPTED

        // First Joe doesn't have Jill anymore
        assertTrue(joe.getDependents().contains("Jack"));
        assertFalse(joe.getDependents().contains("Jill"));

        // Second Joe should still have her
        assertTrue(joe2.getDependents().contains("Jack"));
        assertTrue(joe2.getDependents().contains("Jill"));

If you run this test, poor Second Joe lost his Jill too. It's a shallow clone instead of a
deep clone -- what this does is copy the reference to the dependents, not the dependents themselves.
So if you start fooling around with your original object, you wind up changing things out
from under your clone object. The only way to get around this is to have some code in your
class that knows how to deep-copy the fields you want, which was the original idea behind
Object.clone(). You just can't do the same thing with reflection alone.

So all this really guarantees is that you can copy struct-like objects through reflection,
which is pretty long-winded and time-consuming. A copy constructor would be much simpler.

> Implementation of a CloneBuilder Class
> --------------------------------------
>
>                 Key: LANG-354
>                 URL: https://issues.apache.org/jira/browse/LANG-354
>             Project: Commons Lang
>          Issue Type: New Feature
>            Reporter: Dave Meikle
>            Priority: Minor
>             Fix For: 2.4
>
>         Attachments: CloneBuilder.java, CloneBuilderTest.java
>
>
> As discussed on the Mailing List an implementation of a CloneBuilder class to simplify
creating basic clone methods like the other builders in Lang. Example usage would be as follows:
>  public Object clone() {
>      return CloneBuilder.reflectionClone(this);
>  }
> or
>  public Object clone() {
>      return new CloneBuilder(this)
>          .append("field1")         // note the 'field by name' usage
>          .append("field2")         // rather than 'field by value'
>          ...
>          .append("fieldn")
>          .toClone();
>  }

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


Mime
View raw message