Java访问控制修饰符protected与包的关系

1. 前言

一句话:对同一包内的类和所有子类可见

它的意思是可见需要满足两个条件之一:

  • 调用 protected方法所在类 和 被调用protected方法所在类在相同包下。
  • 调用 protected方法所在类 是 被调用protected方法所在类的子类

需要注意的点是方法所在类。比如子类未重写

下面将通过IDEA的提示来快速分辨各种情况是否可见。

2. 准备

在这里插入图片描述

2.1 被测试类看做父亲、儿子、侄子

父亲儿子在一个包,侄子在另一个包。

ChildOne、ChildTwo、NephewOne、NephewTwo继承Parent。

其中ChildTwoNephewTwo重写了function(),打印语句为自己类的名字。ChildOne、NephewOne不重写方法。

如下列举两个儿子类的内容。侄子同理。

package com.base.child;
import com.base.parent.Parent;
public class ChildOne extends Parent {
}
package com.base.child;
import com.base.parent.Parent;
public class ChildTwo extends Parent {
    @Override
    protected void function(){
        System.out.println("ChildTwo");
    }
}

2.2 Test类的作用

Test在父亲、侄子、外人的包里分别调用各个类的方法验证可见性

public class Test {
    public static void main(String[] args) {
        ChildOne childOne = new ChildOne();
        ChildTwo childTwo = new ChildTwo();
        Parent childOneParent = new ChildOne();
        Parent childTwoParent = new ChildTwo();

        childOne.function();
        childTwo.function();
        childOneParent.function();
        childTwoParent.function();

        NephewOne nephewOne = new NephewOne();
        NephewTwo nephewTwo = new NephewTwo();
        Parent nephewOneParent = new NephewOne();
        Parent nephewTwoParent = new NephewTwo();

        nephewOne.function();
        nephewTwo.function();
        nephewOneParent.function();
        nephewTwoParent.function();
    }
}

2.3 关系

引用类型实际类型是否重写functionfunction所属类所属包
childOneChildOneChildOneParent父包
childTwoChildTwoChildTwoChildTwo父包
childOneParentParentChildOneParent父包
childTwoParentParentChildTwoParent(但使用childTwo的方法)父包
nephewOneParentParentNephewOneParent父包
nephewTwoParentParentNephewTwoParent(但使用NephewTwo的方法)父包
nephewOneNephewOneNephewOneParent父包
nephewTwoNephewTwoNephewTwoNephewTwo侄子包

childOne、childTwo、childOneParent 、childTwoParent 、nephewOneParent 、nephewTwoParent 引用类本身都在父包下。

虽然nephewTwoParent 、nephewOneParent 是侄子类创建的对象,但引用类型为父类型,因此调用nephewTwoParent.function()时调用到了父包下的方法。

nephewOne、nephewTwo类本身在侄子包下。

但是nephewOne未重写function方法,因此调用nephewOne.function()时调用到了父包下。
结论:

调用对象的protected方法时

  1. 如果对象的引用类型定义或重写过该方法,则function所属类和包为其引用类型的类和包。
  2. 如果对象的引用类型未重写过该方法,则function所属类和包未其最近的定义或重写过的父类的类和包。
  3. 子类重写方法,使用了父引用调用方法,那么该方法属于父类(满足第一条),但是实际方法逻辑为子类。

因此只需要关注调用function所属类function所属类 是否在相同包或是其子类即可判断能否可见

3. 验证各个包下是否可见

3.1 父亲包下验证

在这里插入图片描述

发现在父亲包Test类调用侄子包重写的方法失败。

这是因为父亲包下的Test类不与侄子同包,又不是该侄子类的子类

3.2 侄子包下验证

在这里插入图片描述

发现在侄子包Test类调用儿子包所有类的function方法侄子包侄子1父function方法都失败

逐一说明:

  • childOne、childTwo、childOneParent、childTwoParent都在父包下侄子包下的Test类不属于他们的子类包不同,因此无法访问
  • nephewOneParent、nephewTwoParent的类型是Parent类,在父包下。因此包不同且非子类,无法访问。
  • nephewOne 未重写 父类方法,所以调用function方法也是在调用父类方法,所以无法访问。
  • nephewTwo 重写 父类方法,所以调用function方法时,Test类与function所在包相同,可以访问。

3.3 外人包下验证

在这里插入图片描述
包不同且Test非被调用者子类,所以无法访问

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值