详解Java访问修饰符权限范围的具体含义以及调用Object类Clone方法报错原因

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方法,代码如下,请分析。

 

猜你喜欢

转载自blog.csdn.net/yldmkx/article/details/109425882