Solved

Deep Clone Example

Posted on 2014-02-11
11
553 Views
Last Modified: 2014-02-22
Hi,

I am working on below example

http://javapapers.com/core-java/java-clone-shallow-copy-and-deep-copy/

i have not understood what author is mentioning as below relating to deep clone.
Deep Copy
When you need a deep copy then you need to implement it yourself. When the copied object contains some other object its references are copied recursively in deep copy. When you implement deep copy be careful as you might fall for cyclic dependencies. If you don’t want to implement deep copy yourselves then you can go for serialization. It does implements deep copy implicitly and gracefully handling cyclic dependencies.






One more disadvantage with this clone system is that, most of the interface / abstract class writers in java forget to put a public clone method. For example you can take List. So when you want to clone their implementations you have to ignore the abstract type and use actual implementations like ArrayList by name. This completely removes the advantage and goodness of abstractness.

When implementing a singleton pattern, if its superclass implements a public clone() method, to prevent your subclass from using this class’s clone() method to obtain a copy overwrite it and throw an exception of type  CloneNotSupportedException.

Note that clone is not for instantiation and initialization. It should not be synonymously used as creating a new object. Because the constructor of the cloned objects may never get invoked in the process. It is about copying the object in discussion and not creating new. It completely depends on the clone implementation. One more disadvantage (what to do there are so many), clone prevents the use of final fields. We have to find roundabout ways to copy the final fields into the copied object.


My code looks as below

class Employeee implements Cloneable {
	private String name;

	private String designation;

	public Employeee() {
		this.setDesignation("Programmer");
	}

	public String getDesignation() {
		return designation;
	}

	public void setDesignation(String designation) {
		this.designation = designation;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Object clone() throws CloneNotSupportedException {
		/*
		 * CloneExample2222 copyObj = new CloneExample2222();
		 * copyObj.setDesignation(this.designation); copyObj.setName(this.name);
		 * return copyObj;
		 */
		return super.clone();
	}
}

public class CloneExample2222 {
	public static void main(String arg[]) {
		Employeee jwz = new Employeee();
		jwz.setName("Jamie Zawinski");
		try {
			Employeee joel = (Employeee) jwz.clone();
			System.out.println(joel.getName());
			System.out.println(joel.getDesignation());
		} catch (CloneNotSupportedException cnse) {
			System.out.println("Cloneable should be implemented. " + cnse);
		}
	}
}

Open in new window



I got output as below which is also not clear to me

Jamie Zawinski
Programmer

How is implementign cloneable different from sefializable?
please advise
Any links resources ideas highly appreciated. Thanks in advance
0
Comment
Question by:gudii9
  • 6
  • 5
11 Comments
 
LVL 26

Expert Comment

by:dpearson
ID: 39851929
The main point to grasp is the difference between a shallow copy and a deep copy.

This only matters when the object being copied, contains other objects.
E.g.

public MyList {
    private List<String> m_Names ;

    public MyList(List<String> names) { m_Names = names ; }

    public void remove(String name) { m_Names.remove(name) ; }
    public String toString() { return "List=" + m_Names ; }

    public MyList createShallowCopy() {
       MyList newList = new MyList(m_Names) ;
    }

    public MyList createDeepCopy() {
       MyList newList = new ArrayList<String>() ;
       newList.addAll(this.m_Names) ;
       return newList ;
    }
}

Open in new window


Take a look at the differences between createShallowCopy() and createDeepCopy().

Imagine we have:
List<String> names = new ArrayList<String>() ;
names.add("Sam") ;
names.add("Tony") ;
names.add("Lisa") ;
MyList start = new MyList(names) ;

Now if we create a shallow copy:
MyList shallowCopy = start.createShallowCopy() ;
MyList deepCopy = start.createDeepCopy() ;

the list *inside* shallowCopy and start are both the same list.

So if we now do:
start.toString() returns "Sam, Tony, Lisa"
shallowCopy.toString() returns "Sam, Tony, Lisa"
deepCopy.toString() returns "Sam, Tony, Lisa"

start.remove("Sam") ;
start.toString() returns "Tony, Lisa".

But:
shallowCopy.toString() also returns "Tony, Lisa" because the list inside shallowCopy is the same list as the one inside start.

That may be OK, or it may not.  But it's different from deep copy:

deepCopy.toString() returns "Sam, Tony, Lisa" because it contains a different internal list than start does.  So when we removed "Sam" it didn't affect deep copy.

Does that all make sense?

The rest of the article just talks about specifically what clone does (a  shallow copy) and some of the reasons why it's usually best avoided.

Also if you implement serializable you can potentially use that to make a copy since you serialize the data into some form and then deserialize that to get back to the original.  If you do that without throwing away the original then it produces a copy.  So it's one way to copy an object.

Doug
0
 
LVL 7

Author Comment

by:gudii9
ID: 39854622
deepCopy.toString() returns "Sam, Tony, Lisa" because it contains a different internal list than start does.  So when we removed "Sam" it didn't affect deep copy.


How and where do i see to find it contains different internal list. What is the name of internal list deepCopy, shallowCopy has. For me it seems both has same list as below

   public MyList createShallowCopy() {
       MyList newList = new MyList(m_Names) ;
    }

    public MyList createDeepCopy() {
       MyList newList = new ArrayList<String>() ;
       newList.addAll(this.m_Names) ;
       return newList ;
    }
Please advise
0
 
LVL 26

Expert Comment

by:dpearson
ID: 39854695
Oops - my code has some typos which may have thrown you off.

Should be:

 public MyList createShallowCopy() {
       MyList newList = new MyList(m_Names) ;
       return newList ;
    }

    public MyList createDeepCopy() {
       List<String> newInternalList = new ArrayList<String>() ;
       newInternalList.addAll(this.m_Names) ;
       MyList newList = new MyList(newInternalList) ;
       return newList ;
    }

Open in new window


Can you see now how the deep copy is creating a newInternalList while the shallow copy doesn't do that?

Doug
0
 
LVL 7

Author Comment

by:gudii9
ID: 39857357
deepCopy.toString() returns "Sam, Tony, Lisa" because it contains a different internal list than start does.  So when we removed "Sam" it didn't affect deep copy.




 List<String> newInternalList = new ArrayList<String>() ;
       newInternalList.addAll(this.m_Names)


I wonder why  newInternalList  again contains m_Names similar to Shallow Copy.

I did not get the gist of removing list member etc and how it is different in both cases?

I am still not very clear. Can you please post complete code which i can run and see. Please advise
0
 
LVL 7

Author Comment

by:gudii9
ID: 39870615
Can you see now how the deep copy is creating a newInternalList while the shallow copy doesn't do that?


I do not understand clearly.

I modified program as below

 public class MyList {
    private List<String> m_Names ;

    public MyList(List<String> names) { m_Names = names ; }

    public void remove(String name) { m_Names.remove(name) ; }
    public String toString() { return "List=" + m_Names ; }

   public MyList createShallowCopy() {
       MyList newList = new MyList(m_Names) ;
       return newList ;
    }

    public MyList createDeepCopy() {
       List<String> newInternalList = new ArrayList<String>() ;
       newInternalList.addAll(this.m_Names) ;
       MyList newList = new MyList(newInternalList) ;
       return newList ;
    }

}

Open in new window


I see compilation errors like
List cannot be resolved to a type at line 2 and following lines where m_names is used. can you please post complete code. please advise
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 26

Expert Comment

by:dpearson
ID: 39870895
Add this to the top of the file - so it can resolve List:

import java.util.*;

Doug
0
 
LVL 7

Author Comment

by:gudii9
ID: 39871285
import java.util.ArrayList;
import java.util.List;

public class MyList {
    private List<String> m_Names ;

    public MyList(List<String> names) { m_Names = names ; }

    public void remove(String name) { m_Names.remove(name) ; }
    public String toString() { return "List=" + m_Names ; }

   public MyList createShallowCopy() {
       MyList newList = new MyList(m_Names) ;
       return newList ;
    }

    public MyList createDeepCopy() {
       List<String> newInternalList = new ArrayList<String>() ;
       newInternalList.addAll(this.m_Names) ;
       MyList newList = new MyList(newInternalList) ;
       return newList ;
    }

}

Open in new window



It fixed the compilation error once i imported list and array list.

But there is no main method or anything like that. How to run. Can you please provide me complete code to understand this example
0
 
LVL 26

Accepted Solution

by:
dpearson earned 500 total points
ID: 39871489
OK here's a full example, which I hope explains this concept:

import java.util.*;

public class MyList {

	private List<String> m_Names ;

	public MyList(List<String> names) { m_Names = names ; }

	public void remove(String name) { m_Names.remove(name) ; }
	public String toString() { return "List=" + m_Names ; }

	public MyList createShallowCopy() {
		MyList newList = new MyList(m_Names) ;
		return newList ;
	}

	public MyList createDeepCopy() {
		List<String> newInternalList = new ArrayList<String>() ;
		newInternalList.addAll(this.m_Names) ;
		MyList newList = new MyList(newInternalList) ;
		return newList ;
	}

	public static void main(String[] args) {
		List<String> names = new ArrayList() ;
		names.addAll(Arrays.asList(new String[]  { "Alan", "Bill", "Clare" } )) ;

        MyList list1 = new MyList(names) ;
		MyList list2 = list1.createShallowCopy() ;
		MyList list3 = list1.createDeepCopy() ;

		System.out.println("List1 (before change) = " + list1) ;
		System.out.println("List2 (shallow copied) = " + list2) ;
		System.out.println("List3 (deep copied) = " + list3) ;

                // Now we modify the names list - to see which of these
               // "copies" are completely separate copies and which are still
               // sharing data with the original list1.
		names.add("Doug") ;

		System.out.println("List1 (after change) = " + list1) ;
		System.out.println("List2 (shallow copied) = " + list2) ;
		System.out.println("List3 (deep copied) = " + list3) ;
    }
}

Open in new window


The output you should get is:

// See how list1, list2 and list3 are all copies of each other:
List1 (before change) = List=[Alan, Bill, Clare]
List2 (shallow copied) = List=[Alan, Bill, Clare]
List3 (deep copied) = List=[Alan, Bill, Clare]

// But then we modify the internal list "names" to add a new name to it.
// The shallow copy of MyList is sharing the list of names, so it sees the change.
// While the deep copy of MyList creates a new internal list, so it does not see the change.
List1 (after change) = List=[Alan, Bill, Clare, Doug]
List2 (shallow copied) = List=[Alan, Bill, Clare, Doug]
List3 (deep copied) = List=[Alan, Bill, Clare]

The shallow copy and the deep copy behavior are different.  Either may be correct in a given situation - it depends on what you mean by "making a copy of the original".

Does that finally make sense?

Doug
0
 
LVL 7

Author Comment

by:gudii9
ID: 39871603
It makes much more sense. I am still trying to digest.

So the link

http://javapapers.com/core-java/java-clone-shallow-copy-and-deep-copy/


author program is only clone example right which internally uses shallow copy not deep copy.

>>Employee joel = (Employee) jwz.clone();

author in this example using shallow copy(clone) cloned  jamie(jwz) into joe1 object right.
so joe1 name , designation also became same as jamie. So output is

Jamie Zawinski

Programmer


Is my understanding is correct?
0
 
LVL 26

Expert Comment

by:dpearson
ID: 39871757
Yes that's right.  Clone() is a built-in method but it only does a shallow copy.  If you want a deep copy you need to write it yourself.

(There are lots of problems with clone().  The usual advice is to avoid it because unless you're very careful with it, it will do something different from what you want - like this example of a shallow copy).

Doug
0
 
LVL 7

Author Comment

by:gudii9
ID: 39880155
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

An old method to applying the Singleton pattern in your Java code is to check if a static instance, defined in the same class that needs to be instantiated once and only once, is null and then create a new instance; otherwise, the pre-existing insta…
By the end of 1980s, object oriented programming using languages like C++, Simula69 and ObjectPascal gained momentum. It looked like programmers finally found the perfect language. C++ successfully combined the object oriented principles of Simula w…
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now