Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Monday, June 2, 2014

Bitwise and Bit Shift Operators in Java

This post is all about basic understanding of operators that perform bit-wise and bit shift operations on integral types that Java programming language provides.


The bitwise operators:

OperatorNameExampleResultDescription
a & band3 & 511 if both bits are 1.
a | bor 3 | 5 71 if either bit is 1.
a ^ bxor 3 ^ 5 61 if both bits are different.
~anot ~3 -4Inverts the bits.
n << pleft shift3 <<< 212Shifts the bits of n left p positions. Zero bits are shifted into the low-order positions.
n >> pright shift5 >> 21Shifts the bits of n right p positions. If n is a 2's complement signed number, the sign bit is shifted into the high-order positions.
n >>> pright shift-4 >>> 28 15Shifts the bits of n right p positions. Zeros are shifted into the high-order positions.

Note:  "<<<" is not an operator, because it would be redundant. Lets see each operator one by one:

The unary bitwise complement operator:

 

The unary bitwise complement operator "~" inverts a bit pattern; it can be applied to any of the integral types, making every "0" a "1" and every "1" a "0".
 For example: A byte contains 8 bits; applying this operator to a value whose bit pattern is "00000000" would change its pattern to "11111111"

The bitwise & operator:

 

Bitwise AND operator works similar to logical AND operator (&&) and returns 1 if both operands are 1. Difference with bitwise AND and logical AND also known as short-circuit AND operator is that, logical AND operator applies only to boolean type. Also bitwise AND operator is denoted by singe & while short circuit AND operator is denoted by &&. 
For example:If A represent 0010 and B represent 1010 then result of A&B would be 0010.

The bitwise ^ operator:


Bitwise XOR operator is denoted by ^ and also work on individual bits. There is no short-circuit XOR operator in Java and result of bitwise XOR operator is XOR operation of individual bits. see the truth table of XOR operation for predicting result. in short bitwise XOR operators will return 1 if both bits are different and return 0 if both bits are same.

The bitwise | operator:


Bitwise OR operator is also similar to bitwise AND operator and applies to individual bits. It’s different than short-circuit OR operator, which is denoted by (||) and operates on boolean variable. Bitwise OR operator produce result of OR operation on two bits. Like other bitwise operator in Java, bitwise OR is only applicable to integral types.

Left shift (<<)


Integers are stored, in memory, as a series of bits. For example, the number 6 stored as a 32-bit int would be:
00000000 00000000 00000000 00000110
Shifting this bit pattern to the left one position (6 << 1) would result in the number 12:
00000000 00000000 00000000 00001100 
As you can see, the digits have shifted to the left by one position, and the last digit on the right is filled with a zero.

 Note: Shifting left is equivalent to multiplication by powers of 2. So 6 << 1 is equivalent to 6 * 2, and 6 << 3 is equivalent to 6 * 8. A good optimizing compiler will substitute shifts for multiplications when possible.

Non-circular shifting :

 

Please note that these are not circular shifts. Shifting this value to the left by one position (3,758,096,384 << 1):
11100000 00000000 00000000 00000000
results in 3,221,225,472:
11000000 00000000 00000000 00000000
The digit that gets shifted "off the end" is lost. It does not wrap around

Logical right shift (>>>) 


A logical right shift is the converse to the left shift. Rather than moving bits to the left, they simply move to the right. For example, shifting the number 12:
00000000 00000000 00000000 00001100
to the right by one position (12 >>> 1) will get back our original 6:
00000000 00000000 00000000 00000110
So we see that shifting to the right is equivalent to division by powers of 2.

Lost bits are gone

 

However, a shift cannot reclaim "lost" bits. For example, if we shift this pattern:
00111000 00000000 00000000 00000110
to the left 4 positions (939,524,102 << 4), we get 2,147,483,744:
10000000 00000000 00000000 01100000 
and then shifting back ((939,524,102 << 4) >>> 4) we get 134,217,734:
00001000 00000000 00000000 00000110
We cannot get back our original value once we have lost bits.

Arithmetic right shift (>>)

 

The arithmetic right shift is exactly like the logical right shift, except instead of padding with zero, it pads with the most significant bit. This is because the most significant bit is the sign bit, or the bit that distinguishes positive and negative numbers. By padding with the most significant bit, the arithmetic right shift is sign-preserving.

For example, if we interpret this bit pattern as a negative number:
10000000 00000000 00000000 01100000
we have the number -2,147,483,552. Shifting this to the right 4 positions with the arithmetic shift (-2,147,483,552 >> 4) would give us:
11111000 00000000 00000000 00000110
or the number -134,217,722.

So we see that we have preserved the sign of our negative numbers by using the arithmetic right shift, rather than the logical right shift. And once again, we see that we are performing division by powers of 2.

Here a simple java program showing Bit-wise and bit shift operations:


public class tetBitOperator{
 
public static void main(String args[]) {
      int a = 60; /* 60 = 0011 1100 */  
      int b = 13; /* 13 = 0000 1101 */
      int c = 0;

      System.out.println("a="+a);
      System.out.println("b="+b);
      
      c = a & b;       /* 12 = 0000 1100 */ 
      System.out.println("a & b = " + c );

      c = a | b;       /* 61 = 0011 1101 */
      System.out.println("a | b = " + c );

      c = a ^ b;       /* 49 = 0011 0001 */
      System.out.println("a ^ b = " + c );

      c = ~a;          /*-61 = 1100 0011 */
      System.out.println("~a = " + c );

      c = a << 2;     /* 240 = 1111 0000 */
      System.out.println("a << 2 = " + c );

      c = a >> 2;     /* 215 = 1111 */
      System.out.println("a >> 2  = " + c );

      c = a >>> 2;     /* 215 = 0000 1111 */
      System.out.println("a >>> 2 = " + c )
 }
}
 
Output
==========================================================================
a & b = 12
a | b = 61
a ^ b = 49
~a = -61
a << 2 = 240
a >> 2  = 15
a >>> 2 = 15 


Friday, May 30, 2014

Producer Consumer Problem's solution in Java

From the Wikipedia definition,  the producer–consumer problem (also known as the bounded-buffer problem) is a classic example of a multi-process synchronization problem. The problem describes two processes, the producer and the consumer, who share a common, fixed-size buffer used as a queue. The producer's job is to generate a piece of data, put it into the buffer and start again. At the same time, the consumer is consuming the data (i.e., removing it from the buffer) one piece at a time. The problem is to make sure that the producer won't try to add data into the buffer if it's full and that the consumer won't try to remove data from an empty buffer.
The solution for the producer is to either go to sleep or discard data if the buffer is full. The next time the consumer removes an item from the buffer, it notifies the producer, who starts to fill the buffer again. In the same way, the consumer can go to sleep if it finds the buffer to be empty. The next time the producer puts data into the buffer, it wakes up the sleeping consumer. The solution can be reached by means of inter-process communication. An inadequate solution could result in a deadlock where both processes are waiting to be awakened. The problem can also be generalized to have multiple producers and consumers.

In this post I am sharing my producer-consumer solution written in Java.

Producer class:

import java.util.Vector;

public class MyProducer implements Runnable{
 /*taking vector to use as buffer, 
         *it will keep numbers produced by Producer 
  *and work as synchronisation object
        */
 Vector<Integer> sharedQ;
 // Size will store the maximum size of buffer
 int SIZE;
 /*
  * Constructor for Producer class
  */
 public MyProducer(Vector<Integer> sharedQ, final int size) {
  this.sharedQ =sharedQ;
  this.SIZE= size;
 }
 @Override
 public void run() {
  int i=0;
  while(true){
   i++;
   produce(i);
  }
 }
 /*
  * This method has the logic for producing numbers 
         *and synchronization with consumer
  */
 public void produce(int i) {
  //testing if buffer is already full
  while(sharedQ.size() == SIZE) {
   synchronized (sharedQ) {
    try {
     System.out.println("producer waiting...");
     //waiting until some space is made in buffer
     sharedQ.wait();
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
  }
  //adding numbers in buffer
  synchronized(sharedQ) {
   sharedQ.add(i);
   System.out.println("Producer produced: "+i);
   //notifying other thread which are waiting on sharedQ
   sharedQ.notifyAll();
  }
  try {
   /*
    * making thread to sleep for random time after producing  
    *so as to make output more readable and understandable
    *we can set any arbitrary sleeping time
    */
   Thread.sleep(((long)((Math.random())*10000)));
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
 }
}


Consumer class:

import java.util.Vector;

public class MyConsumer implements Runnable {
 
        /*taking vector to use as buffer, 
         *it will keep numbers produced by Producer 
  *and work as synchronisation object
        */ 
        Vector<Integer> sharedQ;
 
 public MyConsumer(Vector<Integer> sharedQ) {
  this.sharedQ = sharedQ;
 }
 
 @Override
 public void run() {
  /*
   * loop will go on forever
   */
  while(true) {
      consumed();
     /*
      * making thread to sleep for random time after consuming  
      *so as to make output more readable and understandable
      *we can set any arbitrary sleeping time
      */
      try {
   Thread.sleep(((long)((Math.random())*20000)));
   
      } catch (InterruptedException e) {   
   e.printStackTrace();
      }
       }
 }
 /*
  * This method has the logic for consuming numbers 
         *and synchronization with producer
  */
 public void consumed() {
  // cheacking if buffer is empty-then consumer has to wait
   while(sharedQ.isEmpty()) {
    synchronized(sharedQ) {
     try {
      System.out.println(Thread.currentThread().getName()+" waiting...");
      sharedQ.wait();
     } catch (InterruptedException e) {
      
      e.printStackTrace();
     }
     
    }
   }
   //consuimng a number from the buffer
   synchronized(sharedQ) {
      System.out.println(Thread.currentThread().getName()+" consumed "+sharedQ.remove(0));
      //notifying other thread which are waiting on sharedQ
      sharedQ.notifyAll();
   }
  }
 
}

  Test class:

import java.util.Vector;

public class MyProducerConsumerTest { 
 
 public static void main(String args[]) {
  
        /*taking vector to use as buffer, 
         *it will keep numbers produced by Producer 
  *and work as synchronisation object
         */  
        Vector<Integer> sharedQ = new Vector<Integer>();
        // Size will store the maximum size of buffer
  final int SIZE = 5;
 //Making producer and consumer thread
 Thread producer = new Thread(new MyProducer(sharedQ,SIZE),"producer");
 Thread consumer = new Thread(new MyConsumer(sharedQ),"consumer");
  
 //starting producer/consumer threads
 producer.start();
 consumer.start();
 /*
  * this join is optional- 
  * after join this main thread will never finish as consumer/producer willl run forever
  * to see effect of join we need to make consumer/producer to run for some specific time
  */
  
 try {
  producer.join();
  consumer.join();
   
 } catch (InterruptedException e) {   
  e.printStackTrace();
 }
 /*
  * this will never get printed 
  * unless we remove join call made above or finish execution of producer/consumer threads
  */
 System.out.println("all done");
 }
}

We can make this code to work for multiple producer/consumer scenario just by changing test class and creating multiple threads for producer and consumer.

Modified Test class:

import java.util.Vector;

public class MyProducerConsumerTest { 
 
 public static void main(String args[]) {
  
        /*taking vector to use as buffer, 
         *it will keep numbers produced by Producer 
  *and work as synchronisation object
         */  
        Vector<Integer> sharedQ = new Vector<Integer>();
        // Size will store the maximum size of buffer
  final int SIZE = 5; 
 
     //Making producer and consumer thread
 Thread producer1 = new Thread(new MyProducer(sharedQ,SIZE),"producer1");
        Thread producer2 = new Thread(new MyProducer(sharedQ,SIZE),"producer2"); 
        Thread producer3 = new Thread(new MyProducer(sharedQ,SIZE),"producer3");
        Thread consumer1 = new Thread(new MyConsumer(sharedQ),"consumer1");
        Thread consumer2 = new Thread(new MyConsumer(sharedQ),"consumer2");
        Thread consumer3 = new Thread(new MyConsumer(sharedQ),"consumer3");
        Thread consumer4 = new Thread(new MyConsumer(sharedQ),"consumer4"); 
  
       //starting producer/consumer threads
 producer1.start();
        producer2.start();
        producer3.start(); 
        consumer1.start();
        consumer2.start();
        consumer3.start();
       consumer4.start(); 
        /*
  * this join is optional- 
  * after join this main thread will never finish as consumer/producer willl run forever
  * to see effect of join we need to make consumer/producer to run for some specific time
  */
  
 try {
  producer1.join();
                producer2.join();
               producer3.join(); 
                consumer1.join();
                consumer2.join();
                consumer3.join();
                consumer4.join(); 
        } catch (InterruptedException e) {   
  e.printStackTrace();
 }
 /*
  * this will never get printed 
  * unless we remove join call made above or finish execution of producer/consumer threads
  */
 System.out.println("all done");
 }
}

 

 

Thursday, May 29, 2014

immutability in Java

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

Immutable objects are particularly useful in concurrent applications. Since they cannot change state, they cannot be corrupted by thread interference or observed in an inconsistent state.

Strategy for Defining Immutable Objects

The following rules define a simple strategy for creating immutable objects.
  1. Don't provide "setter" methods — methods that modify fields or objects referred to by fields.
  2. Make all fields final and private.
  3. Set all instance data in the constructor.
  4. Don't allow sub-classes 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.
  5. 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.
    • Clone mutable objects for which a reference to them is returned.
    • Clone mutable objects for which a reference to them is received.
    • Implement a deep clone if the default shallow clone is not correct for a properly behaved immutable object.
 Lets add all above rules and make something concrete class implementation.
By making class final:

This is the most simple way of making a class mutable.
public final class FinalPersonClass {       

      private final String name;
      private final int age;      

      public FinalPersonClass(final String name, final int age) { 

            super();
            this.name = name;
            this.age = age; 
      } 

      public int getAge() { 

            return age;
      } 

      public String getName() { 

            return name;
      }
} 

 Using Factory methods and making constructor private:

//No need to make class final here 
public class FinalPerson { 
          
     private final String name;
      private final int age;       

      private FinalPerson(final String name, final int age) { 

            super();
            this.name = name;
            this.age = age;
      } 

      public int getAge() { 

            return age;
      } 

      public String getName() { 

            return name; 
      } 

      public FinalPerson getFinalPerson(final String name, final int age) {
           return new FinalPerson(final String name, final int age);
     }
} 


Making a class immutable in Java, which includes mutable member variable.

When an immutable class is implemented, mutable objects passed to or returned from an immutable object must be properly cloned. Consider the following class declarations: a DiskDriveInfo class and a User class. The DiskDriveInfo is intended to be immutable. The User encapsulates which user has shared access to the disk drive. The User object with shared access is stored as part of the DiskDriveInfo object. In the following example, the designer of the class was careful to make the class final and all fields private, and to provide only getter methods. Is the DiskDriveInfo class immutable? If not, what needs to be done to make it so?

class User
{
  private String userName;
  private String userID;
  private int userNode;

  User(String name, int node)
  {
    userName = name;
    userNode = node;
  }
  public void setUserName(String name)
  {
    userName = name;
  }
  public void setUserID(String userid)
  {
    userID = userid;
  }
  public void setUserNode(int node)
  {
    userNode = node;
  }
  public String userName()
  {
    return userName;
  }
}


final class DiskDriveInfo
{
  private int driveSize;
  private String volumeLabel;
  private User driveShare;

  DiskDriveInfo(int size, String volLabel, User share)
  {
    driveSize = size;
    volumeLabel = volLabel;
    driveShare = share;
  }
  public int size()
  {
    return driveSize;
  }
  public String label()
  {
    return volumeLabel;
  }
  public User share()
  {
    return driveShare;
  }
}

The DiskDriveInfo class is not immutable. Objects of this class can be changed. Consider the following code that creates a DiskDriveInfo object and tests its immutability:

class Test
{
  private static final int sizeInMeg = 200;
  public static void main(String args[])
  {
    User share1 = new User("Duke", 10);                       //1
    DiskDriveInfo dd = new DiskDriveInfo(sizeInMeg, "myDrive",
                                         share1);             //2
    User share = dd.share();
    System.out.println("User with shared access is " +
                       share.userName());

    share1.setUserName("Fred");                               //3
    System.out.println("User with shared access is " +
                       share.userName());
  }
}

If we run the program we will get output like this:

Output
================================================================================
User with shared access is Duke
User with shared access is Fred
What went wrong? This code creates a User object, share1, at //1, with the user name Duke. A supposedly immutable DiskDriveInfo object is created at //2 and is passed a reference to the User object. The DiskDriveInfo object is queried, and the shared owner, Duke, is printed. The User object, share1, changes its name to Fred at //3. When the DiskDriveInfo object is queried again for the user name, it discovers that the name changed from Duke to Fred.
The problem is that the DiskDriveInfo constructor receives a reference to the User object and does not make a copy, or clone, of this object. Therefore, the DiskDriveInfo constructor receives a copy of the reference to the User object. Now the DiskDriveInfo object's driveShare field and the local variable, share1, in main of class Test, reference the same object. Therefore, any changes made through either reference affect the same object. Figure shows the object layout after the code at //1 is executed.




http://ptgmedia.pearsoncmg.com/images/art_haggar2_praxis64/elementLinks/haggar2_fig1.gif
 
After the code at //2 is executed, the object layout looks as shown in Figure

http://ptgmedia.pearsoncmg.com/images/art_haggar2_praxis64/elementLinks/haggar2_fig2.gif
Notice that because the reference to the User object is not cloned, both the share1 and driveShare references share the same User object. After the code at //3 is executed, the object layout as shown in Figure.

http://ptgmedia.pearsoncmg.com/images/art_haggar2_praxis64/elementLinks/haggar2_fig3.gif

To correct this problem, the DiskDriveInfo class must clone any mutable object to which it receives a reference. It then has a reference to its own copy of the object that cannot be changed by other code.
The modified DiskDriveInfo class that supports cloning looks like this:


final class DiskDriveInfo
{
  //As before...
  DiskDriveInfo(int size, String volLabel, User share)
  {
    driveSize = size;
    volumeLabel = volLabel;
    driveShare = (User)share.clone();
  }
  public User share()
  {
    return (User)driveShare.clone();
  }
}

 Because you are cloning the User object, its definition must change as well.


class User implements Cloneable
{
  //As before...
  public Object clone()
  {
    try {
      return super.clone();
    }
    catch (CloneNotSupportedException e) {
      //This should not happen, since this class is Cloneable.
      throw new InternalError();
    }
  }
}

 With these changes to the User object, running the previous test code produces the correct output:
Output
================================================================================
User with shared access is Duke
User with shared access is Fred
Because the User object is cloned on the constructor call, the code that subsequently changes the User object at //1 has no effect on the DiskDriveInfo object. The implementation of the immutable DiskDriveInfo class is now correct. The object layout looks as shown in Figure

http://ptgmedia.pearsoncmg.com/images/art_haggar2_praxis64/elementLinks/haggar2_fig4.gif

Achieving Immutability with Builder Design Pattern:

In most of the classes in our real applications there are many fields. Also, most of these fields are not mandatory for object creation. For example, a user in a real application will have a username, password, firstname, lastname, creationDate, emailAddress, etc., but for user creation here, only a username and password are required. 

The Builder Pattern separates the construction of a complex object from its representation so that the same construction process can create different representations.
The builder design pattern provides a way for you to build complex immutable objects. The process is:
  1. The client calls a constructor (or static factory) with all the required parameters and gets a builder object.
  2. The client calls setter like methods to set each optional parameter of interest.
  3. Finally the client calls the build method to generate the object which is immutable.

import java.math.BigDecimal;

/**
* Immutable, hence thread safe CashBalance objec
*/

public final class CashBalance {
  
 private BigDecimal initialBalance, totCredits, totDebits;
  
  //construct
  public CashBalance(CashBalanceBuilder builder) {
  this.initialBalance = builder.initialBalance;
  this.totCredits = builder.totCredits;
  this.totDebits = builder.totDebits;
 }
    
 public static class CashBalanceBuilder {
   
  //has same fields as the object it is going to build
   protected BigDecimal initialBalance, totCredits, totDebits;
  //define the setters that return itself
   CashBalanceBuilder setInitialBalance(BigDecimal initialBalance) {
   this.initialBalance = initialBalance;
   return this;
  }
   CashBalanceBuilder setTotCredits(BigDecimal totCredits) {
    this.totCredits = totCredits;
   return this;
  }
  CashBalanceBuilder setTotDebits(BigDecimal totDebits) {
   this.totDebits = totDebits;
   return this;
  }
 }
  
 //only getter methods and no setter methods as it is an immutable object
}

The client code will look like this :


public static void main(String[] args) {
   CashBalance.CashBalanceBuilder builder = 
           new CashBalance.CashBalanceBuilder(
                    .setInitialBalance(BigDecimal.valueOf(250.00))
                    .setTotCredits(BigDecimal.valueOf(250.00))
                    .setTotDebits(BigDecimal.valueOf(250.00));
                    CashBalance bal = new CashBalance(builder);
}

How to use Date object in immutable class

This is a commonly asked scenario in interviews while discussing about immutable classes.
Some time you may need to write immutable class which includes mutable classes like java.util.Date, 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.
Consider the below code:

public final class ImmutableReminder{

    private final Date remindingDate;
  

    public ImmutableReminder (Date remindingDate)
    {
        if(remindingDate.getTime() < System.currentTimeMillis()){

            throw new IllegalArgumentException("Can not
                   set reminder” + “ for past time: " + remindingDate);
         }
         // creating new object of Date first
this.remindingDate = new Date(remindingDate.getTime());
    }

    public Date getRemindingDate() {
      //returning clone of the date object 
     return (Date) remindingDate.clone();
    }
} 


Wednesday, May 28, 2014

serialVersionUID


When you serialize an object using Serialization mechanism (by implementing Serializable interface), there is a possibility that you may face versioning issues and because of these versioning issues, you will not be able to deserialize the object.



Sections in this post: 
  1. Problem to face
  2. Root of the problem
  3. Solution
  4. What is serialVersionUID
  5. Example
  6. When to update serialVersionUID
    1. Compatible changes
    2. Incompatible changes


Problem scenario....

lets say you created a class, instantiated it, and wrote it out to an object stream. That flattened object sits in the file system for some time. Meanwhile, you update the class file, perhaps adding a new field. Now try to read the flattened object. An exception "java.io.InvalidClassException" will be thrown.

 Root of the problem

lets first see what is actually causing this problem? Why should any change in a serialized class throw "InvalidClassException". During object serialization, the default Java serialization mechanism writes the metadata about the object, which includes the class name, field names and types, and superclass. All this information is stored as part of the serialized object.
When you deserialize the object, this information is read to reconstitute the object. But to perform the deserialization, the object needs to be identified first and this will be done by serialVersionUID. So everytime an object is serialized the java serialization mechanism automatically computes a hash value using ObjectStreamClass’s computeSerialVersionUID() method by passing the class name, sorted member names, modifiers, and interfaces to the secure hash algorithm (SHA), which returns a hash value, the serialVersionUID.

Now when the serilaized object is retrieved, the JVM first evaluates the serialVersionUID of the serialized class and compares the serialVersionUID value with the one of the object. If the sserialVersionUID values match then the object is said to be compatible with the class and hence it is de-serialized. If not InvalidClassException exception is thrown.

 And the solution is...

The solution is very simple. Instead of relying on the JVM to generate the serialVersionUID, you explicitly mention (generate) the serialVersionUID in your class. The syntax is:


 private final static long serialVersionUID = <integer value> 


What is serialVersionUID? 

Its a static, private variable in the class. Once you define the serialVersionUID in your class explicitly, you don't need to update it until and unless you make the incompatible changes.
 
Example:

Consider the same example taken from serialization post to explain the issue and importance of maintaining serialVersionUID.

 

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;

public class MyDateObject implements Serializable{
  
    //first time we keep serial VersionUID as 1L
    private static final long serialVersionUID = 1L;
    private Date date;

    public MyDateObject() {
        //date= Calendar.getInstance().getTime();
         calculateCurrentTime();
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date=date;
     }
   
    private void calculateCurrentTime(){
        date = Calendar.getInstance().getTime();
    }
   
    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
    }

    private void readObject(ObjectInputStream in)
        throws IOException, ClassNotFoundException{

        // our "pseudo-constructor"
        in.defaultReadObject();
        // now perfrom same operation you need to do in constructor
        calculateCurrentTime();
    }
}

 Class to serialize MayDate object :



import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

//Class to persist the time in a flat file time.ser
public class WriteSerialClass {

  public static void main(String [] args) {
      String filename = "c://time.txt";

      if(args.length > 0){
          filename = args[0];
      }
      
      MyDateObject time = new MyDateObject();
      FileOutputStream fos = null;
      ObjectOutputStream out = null;

      try{
          fos = new FileOutputStream(filename);
          out = new ObjectOutputStream(fos);
          out.writeObject(time);
          out.close();
      }catch(IOException ex){
          ex.printStackTrace();
      }
   }
} 

Class to De-serialize MydateObject:


import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Calendar;

public class ReadSerialClass   {

     public static void main(String [] args) {
            String filename = "c://time.txt";

            if(args.length > 0){
                filename = args[0];
            }
           
            MyDateObject time = null;
            FileInputStream fis = null;
            ObjectInputStream in = null;

            try{
                fis = new FileInputStream(filename);
                in = new ObjectInputStream(fis);
                time = (MyDateObject)in.readObject();
                in.close();
            }catch(IOException ex){
                ex.printStackTrace();
            }catch(ClassNotFoundException cnfe){
                cnfe.printStackTrace();
            }

            // print out restored time
            System.out.println("Restored time: " + time.getDate());

            // print out the current time
            System.out.println("Current time: "
                + Calendar.getInstance().getTime());

         }
     } 
Output:
=======================================================
Restored time: Wed May 28 18:11:41 IST 2014
Current time: Wed May 28 18:11:42 IST 2014
 
 

 Now run the following program again by changing serialVersionUID value in myDateObject class:


 
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;

public class MyDateObject implements Serializable{
  
   //Now we change serial VersionUID as 2L
    private static final long serialVersionUID = 2L;
    private Date date;

    public MyDateObject() {
        //date= Calendar.getInstance().getTime();
         calculateCurrentTime();
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date=date;
     }
   
    private void calculateCurrentTime(){
        date = Calendar.getInstance().getTime();
    }
   
    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
    }

    private void readObject(ObjectInputStream in)
        throws IOException, ClassNotFoundException{

        // our "pseudo-constructor"
        in.defaultReadObject();
        // now perfrom same operation you need to do in constructor
        calculateCurrentTime();
    }
}
Output:
=========================================================
java.io.InvalidClassException: com.MyDateObject; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2
    at java.io.ObjectStreamClass.initNonProxy(Unknown Source)
    at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
    at java.io.ObjectInputStream.readClassDesc(Unknown Source)
    at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.readObject(Unknown Source) 

 The reason of the above error is the version change and exactly this is the reason for maintaining the version.
By maintaining version we keep the serialization/de-serialiation consistent

When to update serialVersionUID?

Adding serialVersinUID manually to the class does not mean that it should never be updated and never need not be updated. There is no need to update the serialVersionUID if the change in the class is compatible but it should be updated if the change is incompatible

Some of compatible changes are:
  • Adding field.
  • Adding classes.
  • Removing classes.
  • Adding writeObject/readObject methods.
  • Removing writeObject/readObject methods.
  • Adding java.io.Serializable.
  • Changing the access to a field.
  • Changing a field from static to nonstatic or transient to nontransient.
  Some of the Incompatible changes  are:
  • Deleting fields.
  • Moving classes up or down the hierarchy.
  • Changing a nonstatic field to static or a nontransient field to transient.
  • Changing the declared type of a primitive field.
  • Changing the writeObject or readObject method.
  • Changing a class from Serializable to Externalizable or visa-versa.
  • Removing either Serializable or Externalizable. 
  • Adding the writeReplace or readResolve method. 


Serialization in Java


Serialization is the process of converting an object's state (including its references) to a sequence of bytes, as well as the process of rebuilding those bytes into a live object at some future time.

Sections in this post: 
  1. Some uses of serailization
  2. Serializable Interface
  3. Serialization steps
  4. readObject and writeObjectMethods
  5. FAQ

Serialization is used when you want to persist the object. It is also used by RMI to pass objects between JVMs, either as arguments in a method invocation from a client to a server or as return values from a method invocation. In general, serialization is used when we want the object to exist beyond the lifetime of the JVM. 


Here are some uses of serialization
  • To persist data for future use.
  • To send data to a remote computer using such client/server Java technologies as RMI or socket programming.
  • To "flatten" an object into array of bytes in memory.
  • To exchange data between applets and servlets.
  • To store user session in Web applications.
  • To activate/passivate enterprise java beans.
  • To send objects between the servers in a cluster. 

Java provides Serialization API, a standard mechanism to handle object serialization. To persist an object in java, we need to follow following steps.
  1.  the first step is to flatten the object. For that the respective class should implement "java.io.Serializable" interface. We don't need to implement any methods as this interface do not have any methods. This is a marker interface/tag interface. Marking a class as Serializable indicates the underlying API that this object can be flattened. 


import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;

public class MyDateObject implements Serializable{

    private static final long serialVersionUID = -5315058568373987829L;
    private Date date;

    public MyDateObject() {
        date= Calendar.getInstance().getTime();
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date=date;
     }
}

     2.  Next step is to actually persist the object. To persist an object we need to use node stream to write to file systems or transfer a flattened object across a network. We can use java.io.ObjectOutputStream class for this. So to write an object you use "writeObject(<<instance>>)" method of "java.io.ObjectOutputStream" class and to read an object you use "readObject()" method of "java.io.ObjectOutputStream" class.

Note:  "readObject()" can read only serialized object, that means if the class does not implement "java.io.Serializable" interface, "readObject()" cannot read that object.


import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;


//Class to persist the time in a flat file time.txt
public class WriteSerializeClass {

  public static void main(String [] args) {
       String filename = "c://time.txt";
       if(args.length > 0){
          filename = args[0];
       }       

      MyDateObject time = new MyDateObject();
      FileOutputStream fos = null;
      ObjectOutputStream out = null;

      try{

          fos = new FileOutputStream(filename);
          out = new ObjectOutputStream(fos);
          out.writeObject(time);
          out.close();
      }catch(IOException ex){
          ex.printStackTrace();
      }
   }
}

    

 
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Calendar;
//Class to read the time from a flat file time.txt
public class ReadSerializeClass   {

  public static void main(String [] args) {
         String filename = "c://time.txt";

         if(args.length > 0){
             filename = args[0];
         }
   
         MyDateObject time = null;
         FileInputStream fis = null;
         ObjectInputStream in = null;

         try{
             fis = new FileInputStream(filename);
             in = new ObjectInputStream(fis);
             time = (MyDateObject)in.readObject();
             in.close();
         }catch(IOException ex){
             ex.printStackTrace();
         }catch(ClassNotFoundException cnfe){
             cnfe.printStackTrace();
         }

         // print out restored time
         System.out.println("Restored time: " + time.getDate());

         // print out the current time
         System.out.println("Current time: " 
                      + Calendar.getInstance().getTime());
      }
  }

readObject and writeObject methods:

 To enhance the normal process of serialization/de-serialization provide two methods inside your serializable class. Those methods are:
  1. private void writeObject(ObjectOutputStream out) throws IOException;
  2. private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException; 
   Let's look at one example

Without readObjet()/writeObject()

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;

public class MyDateObject implements Serializable{
    
 
    private static final long serialVersionUID = -5315058568373987829L;
    private Date date;

    public MyDateObject() {
        //date= Calendar.getInstance().getTime();
        calculateCurrentTime();
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
     this.date=date;
     } 
    
    private void calculateCurrentTime(){
        date = Calendar.getInstance().getTime();
    }
 }
Output:
=================================================================

 Restored time: Wed May 28 15:54:31 IST 2014
Current time: Wed May 28 15:54:34 IST 2014

Now we will add the two methods:  readObjet()/writeObject()


import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;

public class MyDateObject implements Serializable{    
 
   private static final long serialVersionUID = -5315058568373987829L;
   private Date date;

    public MyDateObject() {
        //date= Calendar.getInstance().getTime();
        calculateCurrentTime();
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date=date;
     } 
    
    private void calculateCurrentTime(){
        date = Calendar.getInstance().getTime();
    }    //Adding writObject()
    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
    }      //Adding readObject()
    private void readObject(ObjectInputStream in) 
                         throws IOException, ClassNotFoundException{

         in.defaultReadObject();
        // now perfrom same operation you need to do in constructor
        calculateCurrentTime();
    }
}

Output:
=========================================================================
Restored time: Wed May 28 16:08:26 IST 2014
Current time: Wed May 28 16:08:26 IST 2014

 So by overriding these two methods, we can easily get desired serialization/de-serialization behavior.

Note:  serialization does not care about access modifiers. It serializes all private, public and protected fields.

Again there is one more way to serialize the object - create your own protocol with the Externalizable interface. Instead of implementing the Serializable interface, you can implement Externalizable, which contains two methods:
  1. public void writeExternal(ObjectOutput out) throws IOException; 
  2. public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
The Externalization is discussed as separate post. Check it out here .

Some FAQ:
  1. why readObject And writeObject declared as private?
     Ans:  We don't want these methods to be overridden by subclasses. Instead, each class can have its own writeObject method, and the serialization engine will call all of them one after the other. This is only possible with private methods (these are not overridden). (The same is valid for readObject.)
That's why  both methods are declared private . The trick here is that the virtual machine will automatically check to see if either method is declared during the corresponding method call. The virtual machine can call private methods of your class whenever it wants but no other objects can. Thus, the integrity of the class is maintained and the serialization protocol can continue to work as normal. 

 2. How stop from serailizing one of the sub class of a serializable class?

Ans:To stop the automatic serialization, we can once again override the readObject/writeObject  methods to just throw the NotSerializableException in our class.


private void writeObject(ObjectOutputStream out) throws IOException{

    throw new NotSerializableException("Dont Serialize");
}

private void readObject(ObjectInputStream in) throws IOException{

    throw new NotSerializableException("Dont Serialize");
}

     





Tuesday, March 4, 2014

Cloning in Java

A clone is an exact copy of the original. In java, it essentially means the ability to create an object with similar state as the original object.

Sections in this post: 
  1. Default Java cloning
  2. Cloneable Interface
  3. Shallow cloning
  4. Deep cloning
    1. Deep cloning by overriding clone method
    2. Deep cloning using copy constructor
    3. Deep cloning using The factory Method
    4. Deep cloning by Serialzation
  5. Summery

Java cloning

 

By default, java cloning is ‘field by field copy’ i.e. as the Object class does not have idea about the structure of class on which clone() method will be invoked. So, JVM when called for cloning, do following things:

1) If the class has only primitive data type members then a completely new copy of the object will be created and the reference to the new object copy will be returned.

2) If the class contains members of any class type then only the object references to those members are copied and hence the member references in both the original object as well as the cloned object refer to the same object.

In java, if a class needs to support cloning it has to do following things:

A) It must implement Cloneable interface.
B) It must override clone() method from Object class.

Cloneable Interface
public interface Cloneable
A class implements the Cloneable interface to indicate to the Object.clone() method that it is legal for that method to make a field-for-field copy of instances of that class. Invoking Object's clone method on an instance that does not implement the Cloneable interface results in the exception CloneNotSupportedException being thrown.
By convention, classes that implement this interface should override Object.clone (which is protected) with a public method.

Java docs about clone() method says:

1. x.clone() != x will be true
2. x.clone().getClass() == x.getClass() will be true, 
                           but these are not absolute requirements.
3. x.clone().equals(x) will be true, this is not an absolute requirement 
  1.  First statement guarantees that cloned object will have separate memory address assignment.
  2. Second statement suggest that original and cloned objects should have same class type, but it is not mandatory.
  3. Third statement suggest that original and cloned objects should have be equal using equals() method, but it is not mandatory.
Cloning can be categorized in two types:

 

Shallow Cloning 

 

This is default implementation in java. In overridden clone method, if you are not cloning all the object types (not primitives), then you are making a shallow copy. Let's see one example:

Class Employee implements cloneable Interface and has Department as its member variable

public class Employee implements Cloneable{

   private int employeeId;
   private String employeeName;
   private Department department;

   public Employee(int id, String name, Department dept) {
     this.empoyeeId = id;
     this.employeeName = name;
     this.department = dept;
   }   
   
   public int getEmployeeId() {
     return empoyeeId;
   }

   public void setEmployeeId(int employeeId) {
     this.employeeId = empoyeeId;
   }

   public String getEmployeeName() {
     return employeeName;
  }

   public void setEmployeeName(String employeeName) {
     this.employeeName = employeeName;
  }

   public Department getDepartment() {
     return department;
   }

   public void setDepartment(Department department) {
     this.department = department;
   }

   @Override
   protected Object clone() throws CloneNotSupportedException {
     return super.clone();
 }
}
  Class Department:

public class Department
{
 private int id;
 private String name;

 public Department(int id, String name)
 {
  this.id = id;
  this.name = name;
 }

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

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

public class TestCloning {

    public static void main(String[] args)

               throws CloneNotSupportedException {

         Department dept = new Department(1, "Human Resource");
         Employee original = new Employee(1, "Admin", dept); 

        //Lets create a clone of original object

         Employee cloned = (Employee) original.clone();


        //Let verify using employee id, if cloning actually worked

          System.out.println(cloned.getEmpoyeeId());

        //Verify JDK's rules
    //Must be true and objects must have different memory addresses
         System.out.println(original != cloned);

    //As we are returning same class; so it should be true 
         System.out.println(original.getClass() == cloned.getClass());


     //Default equals method checks for references so it should be false.
        // If we want to make it true,
        //we need to override equals method in Employee class.
        System.out.println(original.equals(cloned));
    }
} 
 
Output:
========================================================================== 
 1
true
true
false
 What will happen if we don't implement cloneable Interface???

Check the following code for Class Employee, I have not Implemented Cloneable interface this time but clone method is still there. No compilation error will be shown but when we run the code run-time Exception will come.

public class Employee {

   private int empoyeeId;
   private String employeeName;
   private Department department;

   public Employee(int id, String name, Department dept) {
     this.empoyeeId = id;
     this.employeeName = name;
     this.department = dept;
   }   
   
   public int getEmpoyeeId() {
     return empoyeeId;
 }

 public void setEmpoyeeId(int empoyeeId) {
  this.empoyeeId = empoyeeId;
 }

 public String getEmployeeName() {
  return employeeName;
 }

 public void setEmployeeName(String employeeName) {
  this.employeeName = employeeName;
 }

 public Department getDepartment() {
  return department;
 }

 public void setDepartment(Department department) {
  this.department = department;
 }

 @Override
   protected Object clone() throws CloneNotSupportedException {
     return super.clone();
 }
}

Output
===========================================================================

Exception in thread "main" java.lang.CloneNotSupportedException:
 com.Employee
 at java.lang.Object.clone(Native Method)
 at com.Employee.clone(Employee.java:48)
 at com.TestCloning.main(TestCloning.java:13)
  We can see even if Object class has clone method still we need to implement Cloneable interface to use clone method.

 

Deep cloning


We want a clone which is independent of original and making changes in clone should not affect original.

But before seeing how deep cloning works, lets see what happens when we create two objects of employee class:

public class TestCloning {

 public static void main(String[] args) 
 
  Department hr = new Department(1, "Human Resource");
  Employee original = new Employee(1, "Admin", hr);
  Employee cloned = (Employee) original.clone();

  //Let change the department name in cloned object 
  //and we will verify in original object
  cloned.getDepartment().setName("Finance");

  System.out.println(original.getDepartment().getName());
 }
}

Output: 
========================================================================== 
Finance

cloned object changes are visible in original also. To prevent this from happening we need to do deep cloning.

Let see how it can be done

1. Deep Cloning by overriding clone() 
  Modified clone() method in Employee class

@Override
protected Object clone() throws CloneNotSupportedException {
 Employee cloned = (Employee)super.clone();
 cloned.setDepartment((Department)cloned.getDepartment().clone());
 return cloned;
}
 override clone method in Department class also:
 
@Override
protected Object clone() throws CloneNotSupportedException {
 return super.clone();
}
  Test class:

public class TestCloning {

 public static void main(String[] args) 
                        throws CloneNotSupportedException { 
 
    Department hr = new Department(1, "Human Resource");
    Employee original = new Employee(1, "Admin", hr);
    Employee cloned = (Employee) original.clone();

    //Let's change the department name in cloned object 
                //and we will verify in original object
    cloned.getDepartment().setName("Finance");

   System.out.println(original.getDepartment().getName());
 }
}
 
Output: 
========================================================================== 
Human Resource
So deep cloning requires satisfaction of following rules.
  • All the member classes in original class should support cloning and in clone method of original class in context should call super.clone() on all member classes.
  • If any member class does not support cloning then in clone method, one must create a new instance of that member class and copy all its attributes one by one to new member class object. This new member class object will be set in cloned object.

 

2. Deep Cloning Using Copy Constructors


A copy constructor is a constructor that takes only one argument which is of the type as the class in which the copy constructor is implemented. For example, let us assume a class namely Employee and it has a constructor called copy constructor which expects only one argument of type Employee.

Let’s see an example

public class Employee {

   private int empoyeeId;
   private String employeeName;
   private Department department;

      
   public int getEmpoyeeId() {
     return empoyeeId;
   }

   public void setEmpoyeeId(int empoyeeId) {
     this.empoyeeId = empoyeeId;
   }

   public String getEmployeeName() {
     return employeeName;
  }

   public void setEmployeeName(String employeeName) {
     this.employeeName = employeeName;
  }

   public Department getDepartment() {
     return department;
   }

   public void setDepartment(Department department) {
     this.department = department;
   }
   public Employee(int id, String name, Department department) {

        this.id = id;

        this.name = name;

        this.department = department;

    } 
 
   //copy constructor
public Employee(Employee oldEmployee) {

        this.id = oldEmployee.id;
        this.name = oldEmployee.name;
        this.department = oldEmployee.department;  //shallow cloning
    }
} 
  Class Department:

public class Department
{
 private int id;
 private String name;

 public Department(int id, String name)
 {
  this.id = id;
  this.name = name;
 }

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }
 public Department(int id, String name) {

      this.id = id;

      this.name = name;

 } 
 
  //copy constructor
 public Department(Department oldDepartment) {

      this.id = oldDepartment.id;
      this.name = oldDepartment.name;
  }
 }
  Test Class

public class CopyConstructorTest {
 
 public static void main(String[] args) {

        Department department = new Department(1, "Finance");
        Employee originalEmployee = new Employee(1, "Ram", department);

        Employee clonedEmployee = new Employee(originalEmployee);

        System.out.println("Original:- " + originalEmployee);
        System.out.println("Duplicate:- " + clonedEmployee);
        System.out.println();

        clonedEmployee.setId(2);
        clonedEmployee.setName("Laxman");
        clonedEmployee.getDepartment().setName("HR");

        System.out.println("Original:- " + originalEmployee);
        System.out.println("Duplicate:- " + clonedEmployee);
    }
}
Output
============================================================================
Original:- Employee Id: 1   Employee Name: Ram  Department Id: 1
Department Name: Finance
Duplicate:- Employee Id: 1  Employee Name: Ram  Department Id: 1
Department Name: Finance
Original:- Employee Id: 1   Employee Name: Ram  Department Id: 1
Department Name: HR
Duplicate:- Employee Id: 2  Employee Name: Laxman   Department Id: 1
Department Name: HR
What happens in the above example is, when we change the department name of clonedEmployee, the change comes up with the originalEmployee also. Why it behaves so because what we implement here is shallow cloning

Let’s have a small change in the copy constructor of Employee class to implement Deep cloning 

public Employee(Employee oldEmployee) {
  this.id = oldEmployee.id;
  this.name = oldEmployee.name;
 this.department = newDepartment(oldEmployee.department); //deep cloning
}
  Now we test again and the output is

Original:-  Employee Id: 1  Employee Name: Ram  Department Id: 1    Department Name: Finance
Duplicate:- Employee Id: 1  Employee Name: Ram  Department Id: 1    Department Name: Finance
Original:-  Employee Id: 1  Employee Name: Ram  Department Id: 1    Department Name: Finance
Duplicate:- Employee Id: 2  Employee Name: Laxman   Department Id: 1    Department Name: HR
 Now everything goes fine and this is what we call deep cloning using copy constructors.

But wait until Inheritance comes

let's have one class Manager which inherit Employee

Class Manager:

public class Manager extends Employee{        
private int managerId;
           
    public int getManagerId() {
        return managerId;
    }

    public void setManagerId(int managerId) {
        this.managerId = managerId;
    }

    public Manager (Employee obj, int ManagerId) {
        super(obj);
        this.managerId= ManagerId;
    }
   
    public Manager(Manager obj) {
        super(obj);
        this.managerId= obj.managerId;
    }
}

Test class:

public class TestCloning {        

   public static void main(String[] args) {

        Department department1 = new Department(1, "Finance");
        Department department2 = new Department(2, "It");       

        Employee employee1 = new Employee(1, "Ram", department1);
        Employee employee2 = new Employee(1, "Laxman", department2); 
 
        Manager manager1 = new Manager(employee2,1);
 
        Employee clone1 = new Employee(employee1);
        Employee clone2 = new Employee(manager1);       

        System.out.println("clone1:- " +clone1.toString());
        System.out.println(clone1.getClass());
        System.out.println("clone2:- " + clone2.toString());
        System.out.println(clone2.getClass());
    }
}
Output
===================================================================
clone1:- Employee Id: 1    Employee Name: Ram    Department Id: 1    Department Name: Finance
class com.Employee
clone2:- Employee Id: 1    Employee Name: Laxman    Department Id: 2    Department Name: It
class com.Employee
What just happened here? We passed Manger object to clone2 to but we got Employee class object after cloning.

3. Deep cloning by The Factory Method:

In certain situations we can’t make our copy constructor public, so it has to be private. Now we need to think about an equivalent and yes, fortunately we are able to find out another workaround for achieving the same result- The Factory Method. Let’s have a look.

Class Employee

public class Employee {
    
private String name;
    private int id;
    private Department department;

    public Department getDepartment() {
        return department;
    }
 
    public String getName() {
        return name;
    }

    public int getId() {
        return id;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }

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

    public void setId(int id) {
        this.id = id;
    }

    public Employee(int id, String name, Department department) {
        this.id = id;
        this.name = name;
        this.department = department;
    }

    private Employee(Employee oldEmployee) {
        this.id = oldEmployee.id;
        this.name = oldEmployee.name;
        //deep cloning
        this.department = new Department(oldEmployee.department);
    }

    @Override
    public String toString() {
        return "Employee Id: " + id + "\tEmployee Name: " + name + "\t" 
       + department;
    }

    public static Employee copy(Employee originalEmployee) {
        return new Employee(originalEmployee);
    }
}
Test Class:

public class TestCloning {   
public static void main(String[] args) {

        Department department = new Department(1, "Finance");
        Employee originalEmployee = new Employee(1, "Ram", department);
        Employee clonedEmployee = Employee.copy(originalEmployee);

        System.out.println("Original:- " + originalEmployee);
        System.out.println("Duplicate:- " + clonedEmployee);
        System.out.println();

        clonedEmployee.setEmployeeId(2);
        clonedEmployee.setEmployeeName("Laxman");
        clonedEmployee.getDepartment().setName("HR");

        System.out.println("Original:- " + originalEmployee);
        System.out.println("Duplicate:- " + clonedEmployee);
    }  
}
Output
===================================================================
Original:- Employee Id: 1    Employee Name: Ram    Department Id: 1    Department Name: Finance
Duplicate:- Employee Id: 1    Employee Name: Ram    Department Id: 1    Department Name: Finance

Original:- Employee Id: 1    Employee Name: Ram    Department Id: 1    Department Name: Finance
Duplicate:- Employee Id: 2    Employee Name: Laxman    Department Id: 1    Department Name: HR

4. Deep cloning with serialization

Java serialization is convenient. Many classes are made serializable by simply declaring them to implement java.io.Serializable. Thus, a whole hierarchy of classes can be made cloneable by deriving them from a base Serializable class 

Lets see the code sample:

public Employee clone(Employee obj) {
   
 try
    {
        ByteArrayOutputStream out = new ByteArrayOutputStream ();
        ObjectOutputStream oout = new ObjectOutputStream (out);
        oout.writeObject (obj);
       
        ObjectInputStream in = new ObjectInputStream (
            new ByteArrayInputStream (out.toByteArray ())); 
 
            //This returned Employee object will be a cloned object
return (Employee)in.readObject ();
    }
    catch (Exception e)
    {
        throw new RuntimeException ("cannot clone class [" +
            obj.getClass ().getName () + "] via serialization: " +
            e.toString ());
    }
}
For more details about Serialization refer to serialization in Java.

 

The Summery

 

The following table recaps the properties of all cloning approaches from several perspectives: speed, resource utilization, class design constraints, object graph handling.

Object.clone()
Speed High
Resource utilization Low
Class design constraints Does not work with deep final fields; does not work with inner classes; must implement Cloneable; medium amount of manual class maintenance
Object graphs Does not handle object graphs transparently
Copy construction
Speed High
Resource utilization Low
Class design constraints Superclasses and subclasses must cooperate; copy constructor required; a lot of manual class maintenance
Object graphs Does not handle object graphs transparently
Serialization
Speed Low
Resource utilization High; creates redundant immutable fields
Class design constraints Must implement Serializable; first non-Serializable class needs an accessible no-arg constuctor
Object graphs Handles object graphs
Reflection
Speed Medium
Resource utilization Medium
Class design constraints Does not work with final fields; does not work with inner classes; each class must provide no-arg constructor
Object graphs Handles object graphs