Copy constructor and Copier (@CopyCtor and @CopySetter)

2,714 views
Skip to first unread message

efd

unread,
Jun 25, 2013, 3:16:25 AM6/25/13
to project...@googlegroups.com
Java's default cloning mechanism is discouraged to use, not only because it's difficult to implement a correct one that complies with the contract, but also one must try/catch the messy CloneNotSupported exception that bloats up the codes.
Because of this, on the internet, there are many serializer-based auto cloning libraries. However, first, they use serialization, so dont expect those to be fast, second just for a simple cloning, you must include a huge library -- not quite economical.
Finally one can choose to manually create a clone method which assigns every field with the values from the source object. This is feasible, but very tedious and error prone, especially when someone else modifies the class and fails to change the clone method accordingly.

Now, this provides an excellent opportunity for lombok to shine. With lombok, i think it's quite natural to add a @CopyCtor annotation which generates codes just like the manual cloning while automatically updates when the fields of the class change.
Even better, when no new object is wanted during copying, a @CopySetter annotation would be very useful. It's basically the same of CopyCtor, only that it's not a constructor.

Example:

@CopyCtor
public class Foo {
  private int id;
  private String name;
  @DeepCopy private ArrayList relationaships;
  @SwallowCopy private ArrayList managers;
  private final int rank=2;

  public Foo() {}
}


translates to:

public class Foo {
  private int id;
  private String name;
  private ArrayList relationships;
  private ArrayList managers;
  private final int rank=2;

  public Foo() {}
  public Foo(Foo another) {
    id = another.id;
    name = another.name;
    relationships = Arrays.copyOf( another.relationships );
    managers = another.managers;
  }
}



if CopyCtor and CopySetter are used together, then above codes becomes:

public class Foo {
  private int id;
  private String name;
  private ArrayList relationships;
  private ArrayList managers;
  private final int rank=2;

  public Foo() {}
  public Foo(Foo another) {
    set(another);
  }

  public void set(Foo another) {
    id = another.id;
    name = another.name;
    relationships = Arrays.copyOf( another.relationships );
    managers = another.managers; 
  }
}

Reinier Zwitserloot

unread,
Jun 25, 2013, 9:34:12 AM6/25/13
to project-lombok
The general idea is cool, but it would have 5 pages worth of documentation associated with it. Still possibly worth doing, though. We would presumably hardcode support for how to clone certain types, but there's always the question of how 'deep' a deep copy goes (it should presumably be at all levels, but how do I deep-deep-copy an Arraylist? I can make a new one and fill it with the same references as the old one, but what if you have a list of lists?

In general the problem of deep cloning is very very tricky. And it's something that lombok may have to support 'across the board' - for example, the constructor / builder of a value class probably wants to wash any provided List<T> fields through Collections.unmodifiableList(new ArrayList<T>(original)). However, programmers who care about this sort of thing are probably using guava's ImmutableList, and that one has a significant advantage: If you run ImmutableList.copyOf(input), and input is itself ImmutableList, IL simply returns it. That is a massive performance win especially for large lists.

So now we have to tackle the issue of: Do we just add somethlng like guava=true? Do we scan the compiler classpath and we spot guava, we just use it? Is it acceptable that lombok's behaviour changes depending on what's on your classpath, because so far that's not true, and that can be rather surprising. This rabbit hole is quite deep.



 --Reinier Zwitserloot



--
You received this message because you are subscribed to the Google Groups "Project Lombok" group.
To unsubscribe from this group and stop receiving emails from it, send an email to project-lombo...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Fabrizio Giudici

unread,
Jun 26, 2013, 2:46:41 AM6/26/13
to project-lombok, Reinier Zwitserloot
On Tue, 25 Jun 2013 15:34:12 +0200, Reinier Zwitserloot
<rei...@zwitserloot.com> wrote:

> So now we have to tackle the issue of: Do we just add somethlng like
> guava=true? Do we scan the compiler classpath and we spot guava, we just
> use it? Is it acceptable that lombok's behaviour changes depending on
> what's on your classpath, because so far that's not true, and that can be
> rather surprising. This rabbit hole is quite deep.

I'd definitely appreciate Lombok support for cloning, even though I see
the issues. Using Guava makes sense, but I think that you're right, an
automatic switch that change behaviour in function of the presence/absence
of Guava on the classpath is confusing. We're saying that the compiler
generates different code in function of the presence of a library - sort
of swapping the levels of abstraction.




--
Fabrizio Giudici - Java Architect @ Tidalwave s.a.s.
"We make Java work. Everywhere."
http://tidalwave.it/fabrizio/blog - fabrizio...@tidalwave.it
Reply all
Reply to author
Forward
0 new messages