16

I am confused regarding overriding clone method in the class for which I want cloned object.

Object class has protected object method and as per the protected behavior which is When a method is protected, it can only be accessed by the class itself, subclasses of the class, or classes in the same package as the class.

As every class in Java extends from Object, so it should have clone method but still we are forced to override clone. Why is it required?

Also, I have read at some places to override the clone object and make it public. I wonder, why is it so?

All answers are welcome.

Anand
  • 20,708
  • 48
  • 131
  • 198

5 Answers5

14

As every class in Java extends from Object, so it should have clone method but still we are forced to override clone

No you are not forced to override the clone method. In inheritance, when you inherit a class, you are not forced to override it's method. Its modifier being public or protected doesn't make much of a difference. However, if you want to invoke a method directly on super class reference, then that method has to be public. Protected methods are accessible only through inheritance. That is you can only access them through subclass reference. Or if you override the method, you can access them through super keyword.

Having said that, you should not override clone method, as it is broken. Because, for a class to be cloned, you need to implement the Cloneable interface. And then your class uses the clone method of Object class instead. Because, Cloneable interface doesn't exactly have any method for cloning. It would be a better option to use Copy Constructor instead.

public class A {
   private int data;
   public A() {
   }

   public A(A a) {
      this.data = a.data;
   }
}

For more details, I would suggest to go through this chapter of Joshua Bloch's Effective Java, which covers all aspects of using clone method.

Effective Java- Item # 11 - Override clone judiciously

Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
  • As you wrote that "No you are not forced to override the clone method" but I can't call clone directly on the object if clone is not overridden. Why is it so? – Anand Oct 26 '12 at 18:19
  • @anand. For invoking any method of `super class` you need an instance of that class. Now, if you override the `clone` method, you have that instance of `Object` class as `super`. So, you use `super.clone()` to invoke it. – Rohit Jain Oct 26 '12 at 18:21
  • 1
    @anand. Also, you cannot directly call `clone` method on instance of `Object` class, because `clone` method is `protected`, and is only accessible in `base class` through `inheritance`. So, you can invoke it through the instance of the same class. But be aware, you need to handle `CloneNotSupportedException` – Rohit Jain Oct 26 '12 at 18:23
  • to the above point, clone method is protected in Object class and as per the definition,protected method can be used in subclass and as in Java, every class is subclass of Object, then why can't we directly call clone method on my class's object? – Anand Oct 26 '12 at 18:30
  • @Anand. You can call the clone directly on your class's object. Did you try it? What problem did you have? – Rohit Jain Oct 26 '12 at 18:46
  • In what way is the `clone()` method broken? – Joni Oct 31 '12 at 07:59
  • 1
    @Joni. For cloning an instance, we need to implement `Cloneable` interface. And after that, we actually use the `protected clone` method of the `Object's` class. So, actually `Cloneable` is just the marker interface, and has no `clone` method of its own. And thus we have to use the `clone` method of Object's class. So, you cannot invoke the clone method on an object merely because it implements Cloneable. For more details, I recommend to you go through the link of the book I gave. That is the best resource to understand this thing. – Rohit Jain Oct 31 '12 at 08:12
5

I'd recommend reading Joshua Bloch's Effective Java 2nd edition. It has a good chapter discussing clone.

I would not advise doing this. I consider this a JDK 1.0 mistake. The book will make that clearer.

I'd recommend writing a copy constructor instead to get what you want:

public class Foo {
    private String name;
    public Foo(String name) { this.name = name; }
    public Foo(Foo f) { this.name = f.name; }  // copy ctor here.
}
duffymo
  • 305,152
  • 44
  • 369
  • 561
  • Copy constructor doesn't work with inheritance, that's why we have clone – Steve Kuo Jul 02 '13 at 15:53
  • 1
    Doesn't work? What does that look like? I'd argue that clone doesn't "work" with inheritance either, unless everybody in the chain exhibits great care. Joshua Bloch doesn't say good things about Cloneable in "Effective Java". – duffymo Jul 02 '13 at 17:05
3

In many cases it's not clear what a cloned object should be and how it should behave, so if you want your class to be clonable you have to say so explicitly by overriding clone and making it public.

Cases where clone might not make sense include classes that represent some resource, like a network connection or a synchronization lock. If these objects could be cloned it's not clear how the clone should behave. For example, does the clone of a network connection have a TCP/IP connection of its own or does it somehow use the existing one?

Joni
  • 108,737
  • 14
  • 143
  • 193
2

Clone is Protected method in Object class so it is accessible to you inside class.

About access- When a method is protected, it can only be accessed by the class itself, subclasses of the class, or classes in the same package as the class.

I see some misconceptions about clone method

  1. clone() method is protected inside Object class so you can not call clone() outside of class. e.g. child.clone() unless you override it and make access public
  2. Cloneable is marker interface and if you do not mark class Cloneable then you will get CloneNotSupportedException if you call clone() method
  3. If a class contains only primitive fields or references to immutable objects, then it is usually the case that no fields in the object returned by super.clone need to be modified.
  4. By convention, the returned object should be obtained by calling super.clone. If a class and all of its superclasses (except Object) obey this convention, it will be the case that x.clone().getClass() == x.getClass().

Method signature is below

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

References :

  1. Object#clone()
  2. Cloneable
Amit Deshpande
  • 19,001
  • 4
  • 46
  • 72
-1
    Why we do override clone() in cloning process?
    //clone() in Object class is protected
    package java.lang;


    protected native Object clone()
            throws CloneNotSupportedException;

    java.lang is default import in our java applications.

Note: If parent and sub class are both in same package then the methods in parent class are directly accessible. If they are in different package,then in subclass we have to override the parent class methods to use.

    Note:Object class is in java.lang package,we are using it in different package,so we have to override the clone() which is protected in Object class


first we will look into Protected method behavior.here is sample program to understand this
    //this class is in com.anusha.clonetrial
    package com.anusha.clonetrial;

    public class A {

        public A()
        {

        }
        protected void disp1()
        {
            System.out.println("class a");
        }
        protected void disp2()
        {
            System.out.println("class a");
        }
    }
    //below classes are in com.anusha.Test
    package com.anusha.Test;
    import com.anusha.clonetrial.A;


    class AA {


        protected void disp1()
        {
            System.out.println("class aa");
        }

        protected void disp2()
        {
            System.out.println("class aa");
        }
    }

    //class B derived from AA which is present in the same package
    class B extends AA
    {

        void show()
        {


            System.out.println("class b");
        }
    }

    //class C derived from A which is present in the different package

    class C extends A
    {

        @Override
        protected void disp1()
        {
            super.disp1();
        }
        void show()
        { 
            System.out.println("class c");
        }
    }

    package com.anusha.Test;




    public class CloneTest {


        public static void main(String[] args) {
            B b=new B();
            C c=new C();
            b.disp1();
            b.disp2();
            c.disp1();
            c.disp2();//gives error because it is not overridden.


        }

    }
anusha
  • 1