4

I read Effective Java by J.Bloch and here was wrote:

If you design a class for inheritance, be aware that if you choose not to provide a well-behaved protected clone method, it will be impossible for subclasses to implement Cloneable.

I have Class A:

public class A{}

And class B which extends class A:

public class B extends A implements Cloneable {

}

So in this case I can't to override clone() method? If yes, than please explain why.

7
  • Use copy constructor. Commented May 6, 2015 at 13:56
  • Yes, I understand that copy constructor is a better way to copy object ..thanks :) Commented May 6, 2015 at 14:00
  • For others: An alternative to the copy constructor is the static newInstance() idiom. But I find this curious. Why not simply make your class its own factory and have a non-static newInstance() method? Seems cleaner than passing in an existing object as a parameter; just as the object for a copy of itself (without using the broken clone()). Commented May 6, 2015 at 14:14
  • In the past, I've had a customer who required both shallowClone() and deepClone() customized methods, as an avoidance to the java clone() nonsense. They wanted it entirely under their own control. Makes sense to me. Commented May 6, 2015 at 14:16
  • @tgm1024 so, in real life using clone() method in all cases is a bad idea? Commented May 7, 2015 at 7:52

3 Answers 3

2

In your case yes you can override clone():

public class A {
}

public class B extends A implements Cloneable {

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

and still have an effective clone mechanism - you are therefore telling the truth when you state implements Cloneable.

However, all that is needed to break that promise is to give A a private variable.

public class A {
    private int a;
}

and now your promise is broken - unless A implements clone, in which case you can use super.clone():

public class A {

    private int a;

    @Override
    public A clone() throws CloneNotSupportedException {
        A newA = (A) super.clone();
        newA.a = a;
        return newA;
    }
}

public class B extends A implements Cloneable {

    private int b;

    @Override
    public B clone() throws CloneNotSupportedException {
        B newB = (B) super.clone();
        newB.b = b;
        return newB;
    }
}

Essentially - as Joshua Bloch states - if you don't implement clone your sub-classes also cannot (generally).

Sign up to request clarification or add additional context in comments.

1 Comment

This is simply untrue. The private field in A will be cloned by Object.clone().
1

Cloneable and clone() are pretty much deprecated, so it doesn't matter anyway. However, since clone() is always supposed to call super.clone(), if a superclass implements it wrong, the subclass won't be able to fix it either.

It has nothing to do with not being able to override clone(), it just won't result in a correct implementation.

6 Comments

Where exactly does your first statement (Cloneable is deprecated) come from?
Plenty of discussion about it, here's one place. Actually Cloneable isn't deprecated, it's broken.
Well, I totally agree about the "broken" part. I just thought that I had missed the deprecation part.
@EJP I think the idea I was going for here was that if A doesn't call super.clone() (i.e. Object.clone()), then as B won't be able to call it either it will result in an incorrect implementation. However it seems the doc states that By convention, the returned object should be obtained by calling super.clone(), so I suppose it would just result in an unconventional implementation.
It seems to me that the sentence quoted from Bloch is just simply wrong as stated. Maybe there is some surroundings context that qualifies it. I don't have a copy, and the extracts I've seen from it frankly don't impress me.
|
0

Of course you can implement B.clone().

The problem which J. Bloch refers to is (IIRC), that without a good A.clone() method, the private fields within A can not be cloned properly in B. Simple example:

public class A {
  private String myText;
  public A (String myText) {
    this.myText = myText;
  }
  public String getExtendedText() {
    return "Hello something " + myText;
  }
}

public class B extends A implements Cloneable {
    private int someValue;
    // getter/setter

    public clone() {
        // how can you now provide a good clone with A.myText being cloned?
    }    
}

1 Comment

A.myText and B.someValue will be cloned automatically by Object.clone(). B.clone() doesn't need to do anything beyond calling super.clone() in this instance.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.