0

I have lots of classes and circular references among them (e.g. an in class A, I have a set of objects from class B and class B has an attribute as an object of class A etc.)

When I try to copy everything from an object to another and modify the base object, because of the lists, I lose information.

Is there a way to copy every single bit from an object to another?

Edit:

Consider the following classes

class Book
{
    private Set<Page> pages;
    String title;
}

class Page
{
    private Set<String> lines;
    private int number;
    private int numberOfLines;
    private Book book;
}

should I use Cloneable for both or using just for Book is sufficient?

Could you please help me to write a copy constructor (or a method to copy) for Book class?

padawan
  • 1,295
  • 1
  • 17
  • 45

3 Answers3

3

If your object graph contains only Serializable classes, a common way to do a deep clone is to serialize the initial object and deserialize the result.

You can do this using ObjectOutputStream and ObjectInputStream classes.

Guillaume Darmont
  • 5,002
  • 1
  • 23
  • 35
2

There is no standard out of the box mechanism. The usual way is to implement interface Cloneable or use apache commons utilities - have a look at this answer, or even simply create your own copy constructor manually.

Community
  • 1
  • 1
Angular University
  • 42,341
  • 15
  • 74
  • 81
  • clone() is directly on Object, no need to double-implement the interface. just override it. – MightyPork Apr 18 '14 at 20:50
  • @MightyPork `Object.clone()` - which you need to call to do a shallow field-wise clone - will throw if you don't implement `Cloneable`. – millimoose Apr 18 '14 at 20:51
  • you sure @millimoose? If it's overriden, how can Object intercept the method access? – MightyPork Apr 18 '14 at 20:52
  • 1
    @MightyPork It doesn't intercept anything, but implementations of `clone()` can call `super.clone()` to not have to do the low-level cloning. – millimoose Apr 18 '14 at 20:53
0

Can't you just create a "copy constructor" as you said? It might be more verbose but it's explicit:

class A{
  public A(A other){ 
    bs = new ArrayList<>();
    for(B b : other.bs) bs.add(new B(b));
    /* copy other members */
  }
  private List<B> bs;
}

class B{
  public B(B other){ /* copy all members */ }
}

The advantage is that the intent is explicit. The disadvantage is a lot of boiler plate. As per the alternatives, cloning is not recommended, and serialization incurs quite a performance penalty.

This is a long shot, but you could consider using a tool like ANTLR4 to write a tool to generate the "copy constructors" for you.

Giovanni Botta
  • 9,626
  • 5
  • 51
  • 94