关于访问修饰符——区别与联系

访问修饰符

切勿心急,慢慢看。


先上图网上说法,关于访问修饰符限制范围大家先了解一下:
image_1cl93m0vh1m621dj4e881osu4ck2v.png-28.8kB

上图我从网上找的图,但是说明却不怎么详尽,经过一番思考,不管是类,属性还是方法,作者觉得访问修饰符是从这两个方面来限制他们的:

  • 可见性角度,抑或称可调用性,决定是否可见,即使用。

  • 继承性角度,决定该类方法是否能被它类继承。

访问修饰符 可见性 继承性
private 只在该类里可见 不能被继承
protected 只对同包和子类可见 任意位置继承
默认 只对同包可见 只能被同包的类继承(另一个包的子类不会继承该方法)
public 任意位置可见 任意位置继承

话不多说,我们实验来说明。


关于类的访问修饰符

类前面的修饰符有两种情况,一个是public,还有一个是默认修饰符(即不带任何修饰符)

  1. public:公开

    一个项目的所有包都可以访问到这个类;

  2. 默认修饰符:

    只有当前包可以访问到这个类;

如图所示,存在如下包结构:
TIM截图20180819202609.png-6.9kB
我们将Child类访问修饰符设为默认,Parent设为public:
image_1cl92enj71hr1hjr8dk1hlr1lgc32.png-2.5kB
image_1cl92fhcutvi29gct01sa695l3f.png-3.1kB
我们尝试从另一个包中来声明这两个类的对象:

  1. 声明Child对象时

image_1cl92hd0n1c80lbc1cs8qvgck43s.png-7.3kB
可以看出,其他包中不能声明该类对象。

  1. 声明Parent对象时:

TIM截图20180819202953.png-2.1kB
没有问题。

我们再把Parent访问符设置为默认修饰符让Child继承看看:
image_1cl93ikgeqnb160q154m1ic19c825.png-1.8kB
image_1cl93jhld1dv81ro0ao6oil12is2i.png-3.2kB
也没有报错;
所以可以看出,默认修饰符是“包修饰符”,也就是只有同包的能够访问可见。
关于类的访问修饰符只有这两种情况,可能有人会问为什么类不可以是private或者是protected的呢?(现在讨论的是顶层外部类,内部类不一样哦)
我们可以这么来看,类的上一层容器是包,其次是任意的其它位置,如果外部类能设置成private,这个类被定义后什么用也没有,所以private是没有意义的。如果是protected,前面我们讲过,可见性只在同包中,所以和默认修饰符是一样了,也没有意义。


关于方法的访问修饰符

从最简单的两个说起:

  • private:既然被定义为私有,则只有当前类的成员或者方法才能调用,不能被继承;
  • public:公有开放,则是所有范围都可见,可以继承。

这两个都比较简单,不多赘述。

我们要讨论的是两个特殊情况:

  1. 默认修时符

之前我们讲过,这是一个包修饰符,我们看下效果
我们给Child类定义如下方法:
这里写图片描述
我们在同包的Parent调用Child对象的方法,发现没问题:
这里写图片描述
当我们在另一个包的Repetetive调用Child对象的该方法,发现报错:
这里写图片描述
所以还是那句话,默认修饰符,同包可见,既然同包可见,也只能被同包继承,有图为证:
这里写图片描述

  1. protected修饰符

这个是比较难理解的一个点,网上说法也很不一,找了下官方文档,才有了一个较为确定的说明:
protected可以被任何位置的子类继承,但是它修饰的方法只对同包的类可见。
同样,我们测试让不同包的Repetetive类继承Child类:
这里写图片描述
我们看到Repetetive继承Child后,有自己的protectedfun()函数,却不能调用child的protectedfun();

然而同包的Parent类里可以调用Child对象的protected方法:
这里写图片描述


之前关于访问修时符一直疑惑了很久,今天总算有了一个具体系统的了解了,也是花费了一番功夫,网上也没有从根本上讲解他们区别,最后还是要靠自己参悟。