为何并非所有Java对象都可直接访问clone()方法?
为什么无法直接调用任意对象的
clone()方法 这个问题的核心原因有两个,和Java的访问权限规则、clone()方法的特殊设计有关:
1. protected访问权限的实际限制比常规认知更严格
Java中protected修饰的成员可访问范围的规则是:
- 同包下的所有类可直接访问
- 不同包的子类只能在子类内部访问该子类自身实例的protected成员,不能访问父类实例、其他无关类实例的protected成员
clone()是定义在java.lang.Object类的方法,普通业务类几乎都不在java.lang包下,所以:
- 你无法在自己的代码里直接调用
new Object().clone(),哪怕你写的类是Object的子类 - 你也无法直接调用其他第三方类实例的
clone(),除非你和那个类在同一个包,或者你是那个类的子类且在子类内部访问它的实例
2. clone()方法的调用要求目标类实现Cloneable标记接口
Cloneable是没有任何抽象方法的标记接口,作用是告诉JVM当前类允许克隆。如果目标类没有实现这个接口,哪怕你通过反射等手段绕过了编译限制调用clone(),运行时也会直接抛出CloneNotSupportedException。
通常我们要给自定义类开放克隆能力的时候,都会主动重写clone()方法并把修饰符改为public,方便外部调用,示例如下:
public class User implements Cloneable { private String name; private int age; // 重写clone方法,提升访问权限为public @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } public static void main(String[] args) throws CloneNotSupportedException { User u1 = new User("张三", 20); User u2 = (User) u1.clone(); // 可正常调用 } }
内容的提问来源于stack exchange,提问作者user15599360
相关产品推荐
相关产品推荐

