Posts Tagged clone

Private Fields of Reference Type

Hi, today I stumbled upon a strange problem while wriring some java code.
There is a class with a private field of reference type, say an ArrayList. Now,what is the use of private fields? They are used so that they can not be modified from outside the class like public fields. General practice is to provide getter methods in the class to return the values of private fields.It goes fine with the primitive type variables and Strings(because Strings are immutable). But when the field is of reference type, we can still change its value.Have a look at the code:

import java.util.*;

class Aclass
{

private ArrayList list;
private String s= "My string";

public Aclass()
{
list= new ArrayList();
list.add("Hello");
}

public ArrayList getList()
{
return list;
}

public String getString()
{
return s;
}
}

public class TestPrivate
{

public static void main(String args[])
{
Aclass ob= new a();
ArrayList alist= ob.getList();
System.out.println(l2);
alist.add("Hi");
ArrayList anotherList= ob.getList();
System.out.println(anotherList);

String s2= ob.getString();
System.out.println(s2);
s2="changed";
String s3= ob.getString();
System.out.println(s3);
}
}

When you run this code,the output is:
[Hello]
[Hello, Hi]
My string
My string

You can see that content of list has been changed, but for string, they are not changed.So you can change the list object even if it is private.It is because the getList() method returns the reference to the same list object, so we can modify the list even if it is private.Now if you think that it is some loophole or bug of java,the you are wrong.It is just a simple basic concept of reference type variables.

Now, what should you do to avoid this thing. You have to modify the getList() method so that it returns the clone of list, not the actual list object.Here is the solution:

public ArrayList getList()
{
return (ArrayList) list.clone();
}

clone() will return the clone of object, not the actual list. Return type of clone() is Object, so we have to typecast it to ArrayList. Any modification done from the reference returned by this method will not change the actual one.For more information on clone() method,
go here.

, ,

1 Comment

Problem With clone() if Object Has a Reference Type Attribute

You might have used the clone() method of Object class to get a clone of an object.But have you ever faced a problem if your object has reference type attributes? Well, I have, and thats what I am going to discuss in this post.
A class can have two types of class level variables,primitive type (as int,float) and reference type(as List).Here is an example:

class AClass
{
int i; //primitive type
List alist; //reference type
}
For more on types, click here

Well, lets return on the original topic.When we make a clone of an object, the primitive type variables are copied in the new clone object, but for the reference type variables,only the reference is copied, not the original instance.For example, if we create the clone of above class’s object,there will be only one List object, and both object will have a reference to this.Here is what I tried:

public class ClassToClone {
ArrayList list;
public ClassToClone(ArrayList list)
{
this.list=list;
}

protected Object clone()
{
try{
return super.clone();
}
catch(CloneNotSupportedException e)
{
return null;
}
}
}

To test it:
public class TestClone {
public static void main(String args[])
{
ClassToClone c1,c2;
ArrayList arraylist= new ArrayList();
arraylist.add("Hello");
c1= new ClassToClone(arraylist);
c2 = (ClassToClone)c1.clone();
c1.list.add("Hi"); //change contents of the list of c1
System.out.print(c1.list.toString());
System.out.print(c2.list.toString()); // prints the list of both objects
}
}

When you run this program, you will see that on changing the list of c1, list of c2 is also changed and they both have the same content.
To avoid this problem, you have to explicitly clone the reference type variables. In ClassToClone, replace clone() method by this:

protected Object clone()
{
try{
ClassToClone aobj = (ClassToClone)super.clone();
aobj.s = (ArrayList)list.clone();
//explicit call to clone() for arraylist
return aobj;

}
catch(CloneNotSupportedException e)
{
return null;
}
}

Here we have explicitly cloned the arraylist.Now a new list will be created for clone object.Now changes done in c1.list do not reflect in c2.list.You can try this by yourself.But remember,clone() can be called only if the class implements Cloneable interface, otherwise we get CloneNotSupportedException.Here class ArrayList implements this interface.
Here and here is a great article to read on object cloning.

Leave a comment

Cloning of Objects Using clone() in Java

java.lang.Object class provides a native method clone(). Calling this method on your object will return a clone of that object.”Clone” here means what in normal world the word “clone” means. A clone object is another object having same attribute values as the original object.Here is the how to do cloning of objects:

public class ClassToClone implements Cloneable {
int i;
public ClassToClone(int i)
{
this.i=i;
}
protected Object clone()
{
try
{
return super.clone();
}
catch(CloneNotSupportedException e)
{
return null;
}
} //end of clone method
}//end of class

clone() in Object has protected access. So we have to override the clone() and call super.clone() from it(As Object is superclass of every class). To ensure that our class is cloneable, i.e. it supports cloning functionality, it has to implement java.lang.Cloneable interface.Cloneable inteface does not have any method inside it.It is just a markup interface, used to tell other classes that our class supports cloning.
Now a small note on how it works.When clone() of Object class is called on an object, a new object is created of that class and all the attribute’s values are copied from original to new object.
Now because these two objects are different,calling (obj1==obj2) will give false.
Here and here is a great article about object cloning.

Leave a comment