你可能并不理解访问权限
四大访问权限
四大访问权限修饰下,是否可被不同位置的资源访问。
访问权限 | 含义 | 本类 | 本包(本包子类) | 非本包子类 | 非本包非子类 |
---|---|---|---|---|---|
public | 公共的 | 是 | 是 | 是 | 是 |
protected | 保护访问权限 | 是 | 是 | 是 | 否 |
default | 包访问权限 | 是 | 是 | 否 | 否 |
private | 私有的 | 是 | 否 | 否 | 否 |
关于protected访问权限
谈及protected访问权限时,随口就能说出“同类同包子类”,但结合具体场景时,这里面的坑是不少的,我们用一个案例来说明:
在Object类中,有这样一个方法:
protected native Object clone() throws CloneNotSupportedException;
我们知道任意一个类都继承Object类,也就是说,任意的类都可以可以调用Object的clone()方法,不妨来试一下:
public class Children1 {
public static void main(String[] args) {
Children2 children2 = new Children2();
children2.clone(); //报错
}
}
class Children2 {
}
为什么编译报错呢?在解决上述错误之前,先来回顾两个概念
方法调用
首先需要明确的一个常识是:Java中的“.”并不表示调用,而是表示从属关系,如果在clone()方法前不加一个 children2. 的前缀,那么JVM就不知道具体调用谁的clone()方法了,所以在Java中并不表示children2对象调用了children2的方法(clone方法时主动),而是main方法调用了children2的clone方法(clone是被动地)。
在搞明白上述关系以后,回到访问权限的问题上分析,所谓的访问权限其实就是方法的提供者和方法的调用者之间的关系。在上述案例中:
- 方法提供者:java.lang.Object
- 方法调用者:com.lsj.test1.Children1
父子关系
其次需要明确的是:Java中的protected方法是可以被同类/同包/子类调用的,并且clone()方法是Object的protected方法,是可以被子类对象调用的。在上一段内容说明:调用者是Children1,而被调用者是Object的clone()方法,虽然不是同类不是同包,但貌似是父子关系,为什么“children2.clone()”不能执行呢?因为他们并不是父子关系,这里就要使用“伦理关系”来说明了:虽然张三和李四都管他们的爸爸叫爸爸,但张三的爸爸会是李四的爸爸吗?
显然不是。Children1的main方法试图调用的是children2对象父类的clone()的方法,但是它并没有这样的权利,他只有调用自己父类的clone方法。
而上述案例中演示的其实下面这种调用关系,Children1和Children2的父类Object不满足同类/同包/子类的关系:
Children1的main方法师徒通过Children2来调用Children2的父类的clone()方法,而Children2的父类和Children不满足同类/同包/子类的条件。
如果这里把“children2.clone()”改为“clone() / this.clone”就不会报错了,但是代码的执行效果也不再是克隆一个children2对象。
深刻理解访问权限只需要记住:
- 张三管他的爸爸叫爸爸,李四也管他的爸爸叫爸爸,他们的爸爸都有车,这车只允许自家人开,那你说张三能开李四爸爸的车么?
- 理清方法的调用者和被调用者,并且明确“.”并不表示调用,而是表示从属关系。