用代码详解Java访问控制修饰符

用代码详解Java访问控制修饰符

Java访问控制符是一个很基础的内容,网上介绍的文章也很多,但是许多都讲的不清楚,给我造成了很大的困惑,于是我决定自己写一篇博客,并结合代码,针对default与protected这两个比较难理解的访问控制修饰符做一个比较清楚的介绍。


前言

先让我们来看一张图:
用代码详解Java访问控制修饰符_第1张图片
    这是关于访问权限介绍的一张很经典的图,但是,这张图中的描述有很多令我疑惑的地方。比如,关于default的描述,为什么同包可以,而子类却不行呢?
    由于有许多困惑,而网上搜到的博客又大多不能完全解释我的疑惑,所以我决定通过自己编写代码来真正的理解这些访问控制修饰符。


public&private

    首先,关于这两个修饰符,我觉得还是很好理解的:
    public 无论在哪都可以访问,而 private 则是只能在本类中访问。在这篇博客中就不做过多的阐述了。


default

    从表中可以看出,default的访问权限为:当前类及同包可以,但子类和其他包不行。这里的关键在于:这里的子类代表的是位于其他包下的子类! 如果通过字面意思简单的理解为子类,那就会造成许多困扰了。。。
    下面,我们通过代码来一探究竟。

    首先,我们在pk1下的类A中定义一个变量value,并且不用任何修饰符,即default:
    用代码详解Java访问控制修饰符_第2张图片
    接下来,我们在同一个包下新建一个类A的子类A1并尝试去访问value:
    用代码详解Java访问控制修饰符_第3张图片
    可以到看,是可以访问到的

    然后,同样在pk1下,我们新建一个普通的类Main,并尝试去访问类A的value:
    用代码详解Java访问控制修饰符_第4张图片
    也没有问题,可以访问到

    再然后,我们在另一个包pk2下新建一个类A的子类A2并尝试去访问value:
    用代码详解Java访问控制修饰符_第5张图片
    报错了,访问失败

    最后,我们在包pk2下新建一个普通的类,并尝试去访问value:
    用代码详解Java访问控制修饰符_第6张图片
    同样,也是标红报错,访问失败

    综上,我们在理解default时,其实不必纠结于子类不子类的问题,只要记住,如果使用了default,只有位于同一个包内才有访问权限,而位于其他包中的类,都是没有访问权限的!


protected

    这个修饰符我觉得是四个修饰符中最难理解的一个,因为他有许多“奇妙”的表现,让我借助代码来详细剖析。

    首先,我简单修改了一下上一部分用到的基类A,将value改为private并且新增一个protected的方法getValue():
    用代码详解Java访问控制修饰符_第7张图片

    接下来,在A1中尝试去访问getValue()方法:
    用代码详解Java访问控制修饰符_第8张图片
    没有问题,访问成功

    然后,在pk1.Main类中尝试去访问getValue()方法:
    用代码详解Java访问控制修饰符_第9张图片
    同样也是没有问题,访问成功

    再然后,奇妙的地方出现了,我们在pk2下A的子类A2中用两种方法尝试去访问getValue()方法:
    用代码详解Java访问控制修饰符_第10张图片
    方法1失败而方法2成功

    最后,在pk2下一个普通的类Main中同样用两种方法尝试去访问getValue()方法:
    用代码详解Java访问控制修饰符_第11张图片
    方法1与方法2都失败了!!都!!!失败了。

    由于protected的访问权限比default宽,所以在同一个包下的访问没有问题,这一点并不出乎我们的意料。
    奇妙就奇妙在pk2.A2类和pk2.Main类中发生的情况的对比。
    在类A2中,我用A的实例去访问getValue(),是不允许的,但是,用A2的实例去访问getValue()(即方法2.直接调用getValue()),是允许的。
    在类pk2.Main中,我同样使用了A2中的两种方法,方法1失败了意料之中,但是方法2居然也失败了!这给我造成了很大的困惑,我查阅了很多资料,终于找到了合理的解释
    对于protected修饰符,在同一个包下,其实就等同于default,访问是完全允许的。但是,当在其他包中时,无论什么类,都是不允许通过声明这个protected方法的实例(在本文中,即为A的实例a)来访问这个方法的。而对于不同包下的子类(在本文中,即A2),在没有重写与重载某个protected方法的前提下,只能在本类中访问这个protected方法(因为继承,所以A2其实隐式的继承了这个protected方法),而出了这个类,这个隐式继承来的protected方法又会变得不可见(在本类中,即对应着pk2.Main),所以,pk2.Main中的方法2也就失败了。

    那肯定就有人有疑问了,A2不是继承了这个protected方法吗?为什么pk2.Main会没有访问权限呢?不是与A2位于同一个包嘛?这是因为,当protected出了自己所在的包时,它的含义就变为了“仅对子类可见”(这样才体现了 protected嘛),所以,只有在子类中(A2)才有权限访问这个protected方法!

    那么我非要在pk2.Main中通过A2来访问getValue()方法可以吗?当然可以!只需要在A2中显式的重写一下这个protected方法就好啦,修改后的代码如下:
    用代码详解Java访问控制修饰符_第12张图片
    用代码详解Java访问控制修饰符_第13张图片
    方法2成功访问!撒花~~~~

你可能感兴趣的:(用代码详解Java访问控制修饰符)