1. 访问修饰符
访问修饰符的权限范围不用多讲,通过如下一张表即可表示,但是使用起来却有很多疑问。public修饰符就不用多讲了,在哪都可以访问;无修饰符的也不用多加分析,就是同包下可以访问。接下来我们分析一下protected和private修饰符。
本类 | 同一个包 | 子类 | 其它包 | |
public | √ | √ | √ | √ |
protected | √ | √ | √ | |
无修饰符(也称为package-private) | √ | √ | ||
private | √ |
1.1 protected修饰符
首先,新建两个包 AA_Access 和 AA_Test,然后在包 AA_Access 编写两个类 TestA 和 TestC,在包 AA_Test 编写类 TestB,包目录结构及类代码如下。
不是说protected权限的成员可以被子类访问吗?为什么TestB类继承了TestA类,访问TestA的protected权限方法会报错呢?
其实,是你理解错了。我们再通过一张图来说明以下,如下图。
我们直接访问testProtected方法是正常的,所以你对protected权限有了新的认识吗?protected修饰的成员可以被子类(这里指不同包的子类,同包的子类都不需要考虑protected)访问指父类的protected成员被子类继承,子类可以直接使用;不是在子类方法中创建父类对象,然后通过父类对象调用protected权限的方法。
1.2 private修饰符
不是说private权限的成员可以被本类访问吗?那为什么下图中TestA类对象不能访问private修饰的testPrivate方法呢?
所以private权限的本类访问是指只可以在本类中访问私有权限的成员,即使在外部创建对象,仍然不可以通过对象访问私有权限的成员。
2. 调用clone()方法时报错
我们在实现深克隆时,需要调用对象的clone()方法,因为所有的类默认继承Object类,然后clone()方法是Object中protected修饰的方法,意味着可以被子类继承,所以子类中拥有该方法,也可以直接调用,如下图。
但是我们在同个包的类方法中创建该类对象,然后通过对象调用clone方法却报错了,如下图。
所以我们可以得出结论:从父类所继承的protected方法,如果子类没有重写,那么通过创建对象调用该方法时判断权限,得和父类进行判断是否同包,同包则有调用方法的权限,不同包则没有;如果子类有重写,那么调用方法时判断权限,直接和子类判断是否同包,同包则有调用方法的权限。
当我重写了clone()方法时,程序正常,如下图。
附录
针对前面所说,有点绕,我们再回顾一下。主要有两点:① protected修饰的方法(变量也类似),同包子类不需考虑,不同包子类不可以通过创建父类对象,然后对象.方法来调用。② private修饰的私有方法不可以在外部通过对象.方法调用,只能在本类中被访问。③ 从父类继承的protected方法,如果子类没有重写,那么对象.方法是否可以调用要判断当前类和父类是否同包;如果子类重写,那么对象.方法是否可以调用直接判断当前类和子类是否同包。
接下来是我自己设计的代码段,验证上述结论的同时,可以帮你加深一下理解,看一下你是否理解有些代码可以运行成功,有些代码却报错。不能理解可以在评论区回复。
附录1.
文件目录说明,AA_Access包下有TestA和TestC两个类,AA_Test包下有TestB和TestD两个类,TestC和TestD继承TestA,如下图。
附录1.1 此时父类TestA的子类TestB和TestD没有重写父类的protected方法,类代码如下图所示,请分析。
附录1.2 TestA的子类TestC和TestD重写protected方法的类代码如下,请分析。
附录2.
此时更改文件目录,TestA和TestB和TestD放在包AA_Test下,TestC放在AA_Access包下,但类继承关系没有改变,如下图。
附录2.1 子类TestB和TestD没有重写父类TestA的protected方法,代码如下,请分析。
附录2.2 子类TestC和TestD重写父类protected方法,代码如下,请分析。