Cloneable, Immutable Objects

Cloneable Interface in Java

The Cloneable interface defines no members. It is used to indicate that a class allows a bitwise copy of an object (that is, a clone) to be made. If you try to clone a class that does not implement Cloneable, a CloneNotSupportedException is thrown. When a clone is made, the constructor for the object being cloned is not called. A clone is simply an exact copy of the original. The clone() method is in Object class

protected Object clone() throws CloneNotSupportedException

Lets see an example:


package mynotes.shortConcepts;

class CloneableClass implements Cloneable {

private int x;

public CloneableClass(int x) {
 this.x = x;
 }

public int getX() {

return this.x;
 }

public Object clone() {
 try {
 return super.clone();
 } catch (CloneNotSupportedException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }
 return null;
 }

public CloneableClass testClone() {
 try {
 return (CloneableClass) super.clone();
 } catch (CloneNotSupportedException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }
 return null;
 }

}

public class CloneableClassTest {

public static void main(String[] args) {

CloneableClass obj1 = new CloneableClass(100);
 CloneableClass obj2 = (CloneableClass) obj1.clone();
 CloneableClass obj3 = obj1.testClone();
 System.out.println("obj1="+obj1.getX());
 obj1.setX(0);
 System.out.println("obj1="+obj1.getX());
 System.out.println("obj2="+obj2.getX());
 System.out.println("obj3="+obj3.getX());
 }

}

Result:


obj1=100
obj1=0
obj2=100
obj3=100

Notice we used two ways an object could be cloned one inside a method, one by overriding.

Cloning is a potentially dangerous action, because it can cause unintended side effects. For example, if the object being cloned contains a reference variable called obRef, then when the clone is made,obRef in the clone will refer to the same object as does obRef in the original. If the clone makes a change to the contents of the object referred to by obRef, then it will be changed for the original object, too. Here is another example. If an object opens an I/O stream and is then cloned, two objects will be capable of operating on the same stream. Further, if one of these objects closes the stream, the other object might still attempt to write
to it, causing an error.
Because cloning can cause problems, clone( ) is declared as protected inside Object. This means that it must either be called from within a method defined by the class that implements Cloneable, or it must be explicitly overridden by that class so that it is public.

Java supports two types of Cloning – Shallow Cloning and Deep Cloning.

In case of Shallow cloning a new object is created that has an exact copy of the values in the original object. The clone() method of the Object provides the Shallow cloning. In this cloning mechanism the object is copied without its contained objects. Shallow clone only copies the top level structure of the object not the lower levels, i.e as discussed before, if the class contains another object reference, both the original and cloned class will refer to the same object.

In case of Deep Cloning all the fields are copied. In this case even the objects referenced are copied in the cloned object along with the fields. This can be achieved by making new object for those reference and then mapping with the class. This will ensure that the original and cloned objects doesnot share any common thing that could lead to problems.

Immutable Objects

An object is considered immutable if its state cannot change after it is constructed.

Benefits of making a class immutable:

  • are automatically thread-safe and have no synchronization issues
  • make good Map keys and Set elements (these objects must not change state while in the collection)
  • Another important benefit of Immutable objects is reusability, you can cache Immutable object and reuse them, much like String literals and Integers.  You can use static factory methods to provide methods like valueOf(), which can return an existing Immutable object from cache, instead of creating a new one.

Strategy for Defining Immutable Objects:

  • Don’t provide “setter” methods — methods that modify fields or objects referred to by fields.
  • Make all fields final and private.
  • Don’t allow subclasses to override methods. The simplest way to do this is to declare the class as final. A more sophisticated approach is to make the constructor private and construct instances in factory methods.
  • If the instance fields include references to mutable objects, don’t allow those objects to be changed:
    • Don’t provide methods that modify the mutable objects.
    • Don’t share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.

Let us see this by an example:


package mynotes.shortConcepts;

import java.util.Date;

public class ImmutableClass {

private final String name; //Immutable
 private final String mobile;//Immutable
 private final Date dateOfBirth;//Mutable

public ImmutableClass(String name, String mobile,Date dob) {
 this.name = name;
 this.mobile = mobile;
 this.dateOfBirth=dob;
 }

public String getName() {
 return name;
 }

public String getMobile() {
 return mobile;
 }

 //Here we returned a new object instead of giving reference that could lead to problems
 public Date getDateOfBirth() {
 return (Date)dateOfBirth.clone();
 }

}

Most simple way of creating immutable class in Java, where all fields of class also remains immutable like String, Integer etc. Some time you may need to write immutable class which includes mutable classes like java.util.Date or reference to any other object, despite storing Date into final field it can be modified internally, if internal date is returned to the client. In order to preserve immutability in such cases, its advised to return copy of original object, which is also one of the Java best practice. This copy could be returned by cloning or making a new object and returning.

Why String class is final or immutable? 
It is very useful to have strings implemented as final or immutable objects. Below are some advantages of String Immutability in Java:

  • Immutable objects are thread safe. Two threads can both work on an immutable object at the same time without any possibility of conflict.
  • The absolutely most important reason that String is immutable is that it is used by the class loading mechanism, and thus have profound and fundamental security aspects. Had String been mutable, a request to load “java.io.Writer” could have been changed to load “something.something.DiskErasingWriter”. String has been widely used as parameter for many Java classes e.g. for opening network connection, you can pass hostname and port number as string , you can pass database URL as string for opening database connection, you can open any file in Java by passing name of file as argument to File I/O classes.
  • being immutable String in Java caches its hashcode, and do not calculate every time we call hashcode method of String, which makes it very fast as hashmap key to be used in hashmap in Java.
  • StringPool facility without making string immutable was impossible
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: