Example of using clone()

Implement the Cloneable interface and call super.clone() if to make a bit-by-bit shallow copy. A shallow copy implies that only the references are duplicated in the new object and not the referents. This means that changing a referent in your original object has also an effect on the destination object. To prevent this from happening, you need to make a deep copy, that is manually creating duplicates for the members you don’t want to have shared. If all of your classes implement the Serializable marker interface, you can also make a deep copy by serializing using ObjectOutputStream and deserialize it using ObjectInputStream.
Look what happens in the two following examples.

Shallow copy

Main.java:

public class Main {
   public static void main(String args[]) {
      A a1 = new A();            // create an instance of A
      A a2 = (A) a1.clone();     // shallow-copy clone
 
      a1.sb.append(", world!");  // change the stringbuffer member of the first object
 
      System.out.println(a1);
      System.out.println(a2);    // not that the second object has also changed!
   }
}
 
class A implements Cloneable
{
   public StringBuffer sb = new StringBuffer("Hello");
 
   public String toString() {
      return sb.toString();
   }
 
   public Object clone() {
      try {
         return super.clone();
      } 
      catch(CloneNotSupportedException e) { }
 
      return null;
   }
}

outputs:

Hello, world!
Hello, world!

Deep copy

Main.java:

public class Main {
   public static void main(String args[]) {
      A a1 = new A();            // create an instance of A
      A a2 = (A) a1.clone();     // deep-copy clone
 
      a1.sb.append(", world!");  // change the stringbuffer member of the first object
      System.out.println(a1);
      System.out.println(a2);    // not that the second object has not changed now!
   }
}
 
class A implements Cloneable
{
   public StringBuffer sb = new StringBuffer("Hello");
 
   public String toString() {
      return sb.toString();
   }
 
   public Object clone() {
      try {
         A a = (A) super.clone();
         a.sb = new StringBuffer(sb.toString());
         return a;
      } 
      catch(CloneNotSupportedException e) { }
 
      return null;
   }
}

outputs:

Hello, world!
Hello

For more information on cloning an on whether you should catch the CloneNotSupportedException or specify a throws clause, see the link below.