protected访问权限解释
Object的clone()方法简要介绍
Object类中的clone方法声明为protected,源码如下:
protected native Object clone() throws CloneNotSupportedException;
java中的native关键字表示这个方法是个本地方法。而且native修饰的方法执行效率比非native修饰的高。
protected访问权限解释
protected访问权限允许字段或方法被同一个包下的类访问。此外,对于子类:private限制字段或方法只能在类内部使用,而protected则允许字段或方法能在子类内部使用,但是不允许通过子类的实例在子类外部使用。
如下方:
Object obj1 = obj.clone();
会出错,因为此处不是在Object类内部使用,而是在CloneTest类;- 也正因此,
CloneTest cloneTest1 = (CloneTest) cloneTest.clone();
没有问题。 - 而
MyObject myObj1 = myObj.clone();
报错也是同样的道理。如果在MyObject中实现方法,在方法内部调用this.clone()
,则编译不会报错,不过clone()
方法要求类实现Cloneable
接口,没有接口会出现CloneNotSupportedException
异常。详见后文。
class MyObject {
public void test() throws CloneNotSupportedException {
// 类内部中调用,编译没有问题,但是:
// 因为没有实现Cloneable接口,运行时会出现CloneNotSupportedException异常
Object clone = this.clone();
}
}
public class CloneTest { // Object类的子类
public static void main(String[] args) throws CloneNotSupportedException {
Object obj = new Object();
// 错误:'clone()' has protected access in 'java.lang.Object'
Object obj1 = obj.clone();
MyObject myObj = new MyObject();
// 错误:'clone()' has protected access in 'java.lang.Object'
MyObject myObj1 = myObj.clone();
CloneTest cloneTest = new CloneTest();
// 没有问题:
CloneTest cloneTest1 = (CloneTest) cloneTest.clone();
}
}
使类能够调用clone()方法
在MyObject
类中重写clone()
方法,覆盖掉继承自父类的clone()
方法,则编译通过,不再有因为protected
引起的不可见问题。(注意覆盖方法时,要将权限改成public)
不过,在Object#clone()
的源码中要求,被克隆的类必须实现Cloneable
接口 —— Cloneable
是一个标记接口,它不包含任何方法,唯一的作用是用于在类型检查中通过instanceof
检查。如果没有实现该接口,在克隆时会出现CloneNotSupportedException
异常
class MyObject implements Cloneable{ // 定义一个空类,Object类的子类
public void test() throws CloneNotSupportedException {
// 子类自身中调用,没有问题
Object clone = this.clone();
}
// 注意要将权限改成public,否则不在同个包下且非子类的类中是无法调用protected方法的
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class CloneTest {
public static void main(String[] args) throws CloneNotSupportedException {
MyObject myObj = new MyObject();
// 没有问题
myObj.test();
// 没有问题
MyObject myObj1 = (MyObject) myObj.clone();
}
}
参考
《Java核心技术卷I》第六章
JAVA中的protected(详解),以及和clone()方法有关的一些问题,及博客原文下soloveri的评论:
soloveri: 就是一句话,权限修饰符是针对类的。在子类中,你可以随意使用父类的protected成员。而出了子类,即使在同一包下的其他类就不能访问父类的protected成员了。但是如果又在子类中覆盖了父类的protected成员,在同一包下的其他类又可以访问子类中覆盖的protected成员了,因为子类的protected成员在自身包内都是可见的。