首页 > 解决方案 > 可以在子类的对象上调用受保护的方法而无需覆盖。为什么 java.lang.Object 中的 clone 方法不同?

问题描述

如果我有 A 类

    public class A {
        protected void show() {
        }
    }

另一个B级

    public class B extends A {
    }

驱动类:

    public class Driver {
          public static void main(String[] args) {
                  B b = new B();
                  b.show();
          }
    }

这东西很好用。但是为什么 Object 类中的 clone 方法会有所不同呢?如果我不使用 public 修饰符覆盖 clone 方法,我会收到如下错误:“clone has protected access in Object”。我们知道 Object 默认是所有类的父类。因此,这也应该与类 Driver、A 和 B 的工作方式相同。为什么不同?

标签: javaoverridingclonesubclassprotected

解决方案


来自javadoc

类中的clone()方法必须遵守一些约定:

按照约定,返回的对象应该通过调用 super.clone 来获取。如果一个类及其所有超类(Object 除外)都遵守这个约定,那么 x.clone().getClass() == x.getClass() 就是这种情况。

按照惯例,此方法返回的对象应独立于此对象(正在克隆)。为了实现这种独立性,可能需要在返回 super.clone 之前修改对象的一个​​或多个字段。通常,这意味着复制任何包含被克隆对象的内部“深层结构”的可变对象,并将对这些对象的引用替换为对副本的引用。如果一个类只包含原始字段或对不可变对象的引用,那么通常情况下 super.clone 返回的对象中不需要修改任何字段。

类 Object 的方法 clone 执行特定的克隆操作。首先,如果该对象的类没有实现接口 Cloneable,则抛出 CloneNotSupportedException。请注意,所有数组都被认为实现了接口 Cloneable,并且数组类型 T[] 的克隆方法的返回类型是 T[],其中 T 是任何引用或原始类型。否则,此方法会创建此对象的类的新实例,并使用此对象的相应字段的内容来初始化其所有字段,就像通过赋值一样;字段的内容本身不会被克隆。因此,此方法执行此对象的“浅拷贝”,而不是“深拷贝”操作。

Object 类本身并没有实现接口 Cloneable,因此在类为 Object 的对象上调用 clone 方法将导致在运行时抛出异常。

这意味着您要么必须重写 clone() 方法并实现,要么Cloneable直接使用 clone() 处理抛出的CloneNotSupportedException


推荐阅读