简体   繁体   English

super.clone()操作在派生类中不起作用

[英]super.clone() operation not works in Derived Class

This is raised because of the technical difficulties faced in my Project. 之所以提出这个问题,是因为我的项目面临技术难题。

Problem: I need to clone a Object of a Class where it extended the properties(Inheritance) from a third party library class(where we don't have access to modify its contents) 问题:我需要克隆一个类的对象,在该对象中它扩展了第三方库类的属性(继承)(在该类中,我们无权修改其内容)

Let me explain with example below: 让我用下面的例子解释:

Parent Class: 家长班:

public class UnChangeableBaseClass {

  //fields and Methods

}

Child Class: 儿童班:

class DerivedLocalClass extends UnChangeableBaseClass implements Cloneable {

   // local fields and methods


   public Object clone(){

      Object clonedObj= null;

      try{
       clonedObj = super.clone();
      }
      catch(CloneNotSupportedException e){
        //log exceptions
      }

   }

}

When I try to do this, super.clone() method refers to Class - UnChangeableBaseClass Type and it doesn't overrides the Object clone() methods. 当我尝试执行此操作时, super.clone()方法引用的是Class- UnChangeableBaseClass Type,并且它不会覆盖Object clone()方法。 I believe all classes were extended with java.lang.Object class , implicitly protected Object clone() method would be inherited to this Parent Class. 我相信所有类都使用java.lang.Object class类进行了扩展, protected Object clone()隐式protected Object clone()方法将继承到此Parent类。 So, i thought in such a way that this method in Derived Class would overrides the Parent/Object clone method. 因此,我以这种方式认为派生类中的此方法将覆盖“父/对象”克隆方法。 But during runtime JVM search for the clone method explicitly defined in UnChangeableBaseClass . 但是在运行时JVM中,搜索在UnChangeableBaseClass显式定义的克隆方法。 Hope I explained in proper way without confusing you. 希望我以正确的方式进行解释,不要让您感到困惑。

My questions are follows: 我的问题如下:

  1. How can I implement clone method in this typical case, where we cannot add any method 在这种无法添加任何方法的典型情况下,如何实现克隆方法
    in parent class to have super.clone() to call Object clone method. 在父类中具有super.clone()来调用对象克隆方法。

  2. If above case is not possible, is there any other way to clone the Derived Class 如果以上情况是不可能的,是否有其他方法可以克隆派生类
    Object (by considering all the limitations in above scenario) 对象(考虑上述情况下的所有限制)

  3. Finally, just to know the reason for this JVM behaviour (described above). 最后,仅要了解这种JVM行为的原因(如上所述)。

How can I implement clone method in this typical case, where we cannot add any method in parent class to have super.clone() to call Object clone method. 在这种典型情况下,我们如何实现克隆方法,在这种情况下,我们不能在父类中添加任何方法来让super.clone()调用对象克隆方法。

Well, since clone method is a protected method in Object class, so it is accessible in your super class UnChangeableBaseClass also, since it extends from Object class. 好吧,由于clone方法是Object类中的一种受保护方法,因此,由于clone方法是从Object类扩展的,因此在超级类UnChangeableBaseClass也可以访问它。 So, basically you can access the clone method, using super.clone() , from your base class DerivedLocalClass . 因此,基本上,您可以使用super.clone()从基类DerivedLocalClass访问clone方法。

If above case is not possible, Is there any other way to clone the Derived Class Object (by considering all the limitations in above scenario) 如果以上情况不可能,是否有其他方法克隆派生类对象(通过考虑上述情况中的所有限制)

I would suggest, even though you have the option to use clone method to clone the object, you should not use it. 我建议,即使您可以选择使用clone方法来克隆对象,也不应使用它。 It would be better to use a copy-constructor in your derived class, and add a super() call to the base class constructor. 最好在派生类中使用copy-constructor ,然后向基类构造函数中添加一个super()调用。

Also, see Effective Java - Item#11 - Override clone judiciously , which suggest that clone method is broken. 另请参阅Effective Java - Item#11 - Override clone judiciously ,这表明clone方法已损坏。

In this article: - Josh Bloch on Design - Copy Constructor versus Cloning , you would like to see the very first paragraph of Bloch : - 在本文中: Josh Bloch on Design - Copy Constructor versus Cloning ,您希望看到Bloch第一段:-

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. 如果您已经阅读了我书中有关克隆的内容,尤其是您在两行之间阅读的话,您会知道我认为克隆已被严重打破。 There are a few design flaws, the biggest of which is that the Cloneable interface does not have a clone method. 存在一些设计缺陷,其中最大的缺陷是Cloneable接口没有克隆方法。 And that means it simply doesn't work: making something Cloneable doesn't say anything about what you can do with it. 这意味着它根本行不通:制作可克隆内容并不能说明您可以使用它做什么。 Instead, it says something about what it can do internally. 相反,它说明了其内部功能。 It says that if by calling super.clone repeatedly it ends up calling Object's clone method, this method will return a field copy of the original. 它说,如果通过重复调用super.clone最终导致调用Object的clone方法,则此方法将返回原始字段的副本。

So, conclusion is that, you can have a copy constructor in your DerivedLocalClass , which will return you the copy of the invoking object, something like this: - 因此,结论是,您可以在DerivedLocalClass拥有一个copy constructor ,该copy constructor将向您返回调用对象的副本,如下所示:-

public DerivedLocalClass(DerivedLocalClass obj) {
    this.setVar(obj.getVar());
}

JVM Cloning works by making use of the Marker interface Cloneable rather than looking for Object.clone(). JVM克隆通过使用Marker接口Cloneable而不是寻找Object.clone()来工作。 It is true that all the Java Classes will inherit clone method but according to javadoc for Cloneable 的确,所有Java类都将继承clone方法,但是根据javadoc的说法,它是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.

In your case you can't do super.clone() because it is not marked to be Cloneable. 在您的情况下,您不能执行super.clone(),因为它没有被标记为可克隆。 If you cannot change the parent class then you will have to make a Copy of it yourself. 如果您不能更改父类,则必须自己复制它。

I am using java 1.7 and I don't get any problem in running the code given by OP. 我正在使用Java 1.7,在运行OP给定的代码时没有任何问题。 Unless the superclass has overridden clone to throw an exception I think this should work even if the superclass does not declare itself clonable. 除非超类具有重写的克隆以引发异常,否则我认为即使超类未声明自身可克隆,此方法也应起作用。

I will note that 我会注意到

public Object clone()

is not overriding the clone method, its missing the throws clause. 没有覆盖clone方法,它缺少throws子句。

Correct Method signature is below 正确的方法签名如下

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

Clone is Protected method in Object class so it is accessible to you inside class, and if you are extending from it. Clone是Object类中的Protected方法,因此您可以在类内部以及从其进行扩展时访问。 super.clone() is just needed to call clone() method from object which calls method internalClone on this which is current class object. super.clone()仅需要从对象上调用clone()方法,该对象在当前类对象上this方法调用internalClone

   internalClone((Cloneable) this);

So above clone() method inside Object will only throw CloneNotSupportedException if instance on which it is called is not Cloneable 因此,如果调用Object实例不是Cloneable ,则Object内部的上面clone()方法只会抛出CloneNotSupportedException

I see some misconceptions about clone method 我看到一些关于克隆方法的误解

  1. clone() method is protected inside Object class so you can not call clone() outside of class. clone()方法在Object类内部protected因此您不能在类外部调用clone() eg child.clone() unless you override it and make access public 例如child.clone()除非您覆盖它并public访问
  2. Cloneable is marker interface and if you do not mark class Cloneable then you will get CloneNotSupportedException if you call clone() method Cloneable是标记接口,如果不标记Cloneable类,则调用clone()方法将得到CloneNotSupportedException
  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. 如果一个类仅包含基本字段或对不可变对象的引用,则通常情况是无需修改super.clone返回的对象中的任何字段。
  4. By convention, the returned object should be obtained by calling super.clone . 按照惯例,应通过调用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() . 如果一个类及其所有superclasses (except Object)遵守此约定,则x.clone().getClass() == x.getClass()

So below code works fine 所以下面的代码可以正常工作

public  class Child extends UnChangeableBaseClass
        implements
            Cloneable {

    int index = 0;

    public Child(int index) {

        this.index = 10;
    }
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

}

References : 参考文献:

  1. Object#clone() 对象#克隆()
  2. Cloneable 可复制

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM