protected访问权限解释——以Object的clone()方法为例

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成员在自身包内都是可见的。

Object的clone()方法的使用

java object 之clone方法解析

上一篇:C# protected修饰符


下一篇:android学习笔记7--------MVC设计模式