3

i tried the following code for cloning the object. while compiling it shows clone is protected and cannot be accessed, but i had extended Object class, hence the clone method will be public to my class . please explain me the reason.

class storeDate extends Object {

  public static void main(String[] args)
  {

    storeDate d = new storeDate();
    Object o = (storeDate)d;
    o.clone():
  }

}

while compilation i get this error

clone() has protected access in java.lang.Object kkk.clone();

Suresh S
  • 31
  • 1
  • 4

3 Answers3

1

You should override and implement the clone method from Object. Then you can call clone() or super.clone() if you need the method body from Object.clone. The standard implementation just clones primitive types and references to other objects.

And the subclass needs to implement the interface Cloneable (which is just a marker interface with no methods to implement).


(Back to your question) Object itself is not cloneable (doesn't implement Cloneable) and thus can't be cloned. And because Object#clone is implemented as a protected method, any subclass of Object (= every class in fact) can access its inherited clone() method and every class inside the 'java.langpackage can accessclone()` methods from other objects too.

For a quick understanding of modifiers see this nice matrix.

Andreas Dolk
  • 113,398
  • 19
  • 180
  • 268
  • ok. But super.clone() won't do it since he wants to do "thatOtherObject.clone()"? or did I misunderstand something? :\ – aioobe Jun 10 '10 at 07:15
  • @Andreas_D since i extend Object class the protected member will be public to the subclass . so i can cast to object type and call Object's clone method without overriding. – Suresh S Jun 10 '10 at 07:15
  • @Andreas_D while compiling i get this error clone() has protected access in java.lang.Object kkk.clone(); – Suresh S Jun 10 '10 at 07:20
  • ... sorry, I was still editing and improving the answer - the first 'release' wasn't actually good and helpful – Andreas Dolk Jun 10 '10 at 07:21
  • But why does this work then: `class A { protected void hello() {} } public class B extends A { public static void main(String args[]) { new B().hello(); } }` ? – aioobe Jun 10 '10 at 07:26
  • @aioobe - you're right and I hope my actual answer is much better - the `thatOtherObject.clone()` will require overriding the clone() method and declaring the overriding method as `public`. – Andreas Dolk Jun 10 '10 at 07:27
  • @aioobe - because a subclass has access to protected methods of it's superclass !? – Andreas Dolk Jun 10 '10 at 07:28
  • Thanks for your patience :) I mixing up the situation with something similar. Sorry! – aioobe Jun 10 '10 at 07:33
  • I actually don't think this answer explains the issue really. See my answer. – aioobe Jun 10 '10 at 07:54
  • The matrix "does" explain it: "Class SubB has access only to the inherited from Base protected elements, i.e. its own elements, but the protected data of other Base instances is not accessible from SubB." – Jean Hominal Jun 10 '10 at 08:03
  • Sure. The link to the matrix explains it, but this answer does not even mention the word "package". – aioobe Jun 10 '10 at 08:13
  • 13 comments plus this one so far, how many more to get a badge? :-)) – Andreas Dolk Jun 10 '10 at 08:47
  • 1
    package java.lang results in SecurityException: Prohibited package name: java.lang – aioobe Jun 10 '10 at 09:04
  • (that's what I expected - thanks for mentioning it, I don't have an IDE at hand, maybe I have a look at it tonight, if there's a way around this 'issue' :-) ) – Andreas Dolk Jun 10 '10 at 09:26
  • The SystemClassloader has hardcoded security checks if the package name of a class starts with 'java' (although java accepts the java.* packages in rt.jar... ;) ) inside final methods. Apart from 'patching' classes in rt.jar - no chance adding a class to the java.lang package. Thanks for making me learn something new ;) – Andreas Dolk Jun 10 '10 at 10:00
1

Do you absolutely have to use clone? Most people agree that Java's clone is broken.

Josh Bloch on Design - Copy Constructor versus Cloning

If you've read the item about cloning in my book, especially if you read between the lines, you will know that I think clone is deeply broken. [...] It's a shame that Cloneable is broken, but it happens.

You may read more discussion on the topic in his book Effective Java 2nd Edition, Item 11: Override clone judiciously. He recommends instead to use a copy constructor or copy factory.

He went on to write pages of pages on how, if you feel you must, you should implement clone. But he closed with this:

Is all this complexities really necessary? Rarely. If you extend a class that implements Cloneable, you have little choice but to implement a well-behaved clone method. Otherwise, you are better off providing alternative means of object copying, or simply not providing the capability.

The emphasis was his, not mine. The entire item is a must read to understand the issues deeper and to consider alternatives.

Related questions


So how to copy objects?

Here's a quote from the book:

A fine approach to object copying is to provide a copy constructor or copy factory.

In this case, it can be implemented simply with providing a StoreDate constructor that takes another StoreDate, or providing a utility method static StoreDate newInstanceFrom(StoreDate other).

Related questions

Community
  • 1
  • 1
polygenelubricants
  • 376,812
  • 128
  • 561
  • 623
  • 1
    You're avoiding the question. The answer is that it has to do with the fact that storeDate and Object belong to different packages. – aioobe Jun 10 '10 at 07:54
1

The key thing here is which package the classes belongs to.

This is explained in JLS paragraph 6.6.2:

6.6.2 Details on protected Access
A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object.


Examples:

This does not compile:

FILE pkg1/A.java (corresponds to the Object class in your question)

package pkg1;
public class A {
    protected void method() {};
}

FILE pkg2/B.java (corresponds to storeDate in your question)

package pkg2;
import pkg1.A;
public class B extends A {
    public static void main(String args[]) {
        new A().method();
    }
}

javac outputs the following:

pkg2/B.java:5: method() has protected access in pkg1.A
        new A().method();
               ^

(which is similar to what you have: clone() has protected access in java.lang.Object kkk.clone();)


Simply moving B to the pkg1 package solves it.

That is, this does compile:

FILE pkg1/A.java (unchanged)

package pkg1;
public class A {
    protected void method() {};
}

FILE pkg1/B.java (moved from pkg2 to pkg1)

package pkg1;                 // Changed from pkg2
//import pkg1.A;              // Not necessary anymore.
public class B extends A {
    public static void main(String args[]) {
        new A().method();
    }
}

So, what would have been required for you to be able to do something like new Object().clone()? Well, you would have to belong to the java.lang package (which in turn, however results in a SecurityException: Prohibited package name: java.lang).

aioobe
  • 413,195
  • 112
  • 811
  • 826