Java 中的权限修饰符(protected)

Java 中的权限修饰符(protected)

大部分来自 protected 加了一些自己的理解

权限控制表
在这里插入图片描述
在学到cloned方法时,看到这样一句话
Object类中的clone方法声明为protected,所以你的代码不能直接调用anObject.clone()。但是,不是所有的子类都可以访问受保护的方法吗?不是所以的类都是Object的子类吗?辛运的是,受保护访问的规则比较微妙。子类只能调用受保护的clone方法来克隆它自己的对象。必须重新定义clone为public才能允许所有方法可隆对象。
我在想这话说的不是很对的,不是所有类都是Object的子类吗,为什么还要声明为protected呢,在查阅相关资料后,我得出了一些结论。

首先要了解protected的真正访问权限
1.父类的protected 方法的可见性是同包内和子类

2.若子类与父类不在同一包中,那么在子类中,子类实例可以访问其从父类继承而来的protected方法,而不能访父类实例的protected方法。

第一句话好理解,但对于第二句话你可能不知道在说什么,且不急,继续往下看,你就会明白

示例一
p1/Father1.java

package basic.testprotected.p1;

public class Father1 {
    protected void f() {}    // 父类Father1中的protected方法
}

p1/Son1.java

package basic.testprotected.p1;

public class Son1 extends Father1{}

p11/Son11.java

package basic.testprotected.p11;

import basic.testprotected.p1.Father1;

public class Son11 extends Father1{}

p1/Test1.java

在这里插入图片描述
首先看(1)(3),其中的f()方法从类Father1继承而来,其可见性是包p1及其子类Son1和Son11,而由于调用f()方法的类Test1所在的包也是p1,因此(1)(3)处编译通过。也就是说,如果我们换一个包,比如Test11.java在p11下,那么将都不可访问。如下:
在这里插入图片描述
其次看(2)(4),其中的clone()方法的可见性是java.lang包及其所有子类,对于语句son1.clone();和son11.clone();,二者的clone()在类Son1、Son11中是可见的,但对Test1是不可见的,因此(1)(3)处编译不通过。也就是说,如果在Son1或Son11这两个类中调用clone()方法,则是可以编译通过的。
在这里插入图片描述

示例二
p2/MyObject2.java

package basic.testprotected.p2;

public class MyObject2 {
    protected Object clone() throws CloneNotSupportedException{
        return super.clone();
    }
}

p22/Test2.java
在这里插入图片描述
对于(1)而言,clone()方法来自于类MyObject2本身,因此其可见性为包p2及MyObject2的子类,虽然Test2是MyObject2的子类,但在Test2中不能访问父类MyObject2的protected方法clone(),因此编译不通过; 对于(2)而言,由于在Test2中访问的是其本身实例的从父类MyObject2继承来的的clone(),因此编译通过。所以在这里,就很好地阐述了上面所给的第二条结论:

若子类与父类不在同一包中,那么在子类中,子类实例可以访问其从父类继承而来的protected方法,而不能访问父类实例的protected方法。

为什么要这样以及这样要如何解释呢?
在这里插入图片描述
在这里插入图片描述
至此我们得出在子类中只能通过子类实例克隆本子类对象,而不能克隆其他子类对象(实现了Cloneable接口,重写clone方法的子类对象除外)

因此我们剖析了protected的访问权限,也可以很容易理解为什么clone方法为什么要声明成protected

clone写成protected的真正原因是设计者希望子类只能调用保护的clone方法克隆他自己的对象,而不能克隆其他对象,但子类可能存在需要深拷贝或不可拷贝的字段,但不能保证子类的设计者一定会修正clone方法让其正常工作,处于安全性考虑,在Object类中将其声明为protected,这也是为什么要进行深拷贝时要改protected为public,此时就可以clone其他对象了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值