You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

跨包子类访问父类protected字段的权限差异问题解析

Java中protected访问权限的规则解析

先看涉及的核心代码:

父类代码(test1.visibility包)

package test1.visibility;

public class Test {
    private int privateField = 1;
    int defaultField = 2;
    protected int protectedField = 3;
}

子类代码(test2.visibility包)

package test2.visibility;    

import test1.visibility.Test;
    
public class ExtendsTestOutsideThePackage extends Test {
    public static void main(String[] args) {
        Test tt = new Test();
        Test te = new ExtendsTestOutsideThePackage();
        ExtendsTestOutsideThePackage ee = new ExtendsTestOutsideThePackage();
    
        // 以下为关键代码行
        System.out.println(tt.protectedField); //compilation error
        System.out.println(te.protectedField); //compilation error
        System.out.println(ee.protectedField); //works fine
    }
}

针对三个关键代码行的解释

要搞清楚原因,得先明确Java中protected权限的核心规则:不同包的子类只能通过自身类型的引用访问父类的protected成员,不能通过父类类型的引用访问,也不能直接访问父类的实例。

  • 第1行报错原因:tt是父类Test的直接实例,当前类和Test分属不同包。protected权限并没有赋予外部包类直接访问父类实例成员的权利,所以编译报错。
  • 第2行报错原因:te的引用类型是父类Test,虽然实际对象是子类ExtendsTestOutsideThePackage,但Java的访问权限检查是基于引用类型而非实际对象类型的。因为引用类型是不同包的父类,所以无法访问protected成员。
  • 第3行正常运行原因:ee的引用类型是子类ExtendsTestOutsideThePackage,也就是当前类本身。作为不同包的子类,Java允许通过自身类型的引用访问父类的protected成员,所以代码可以正常编译运行。

总结

  • 不同包下,不能直接通过父类实例访问protected成员(对应tt的情况)。
  • 哪怕实际对象是子类,只要引用类型是父类,不同包下也无法访问protected成员(对应te的情况)。
  • 只有通过子类自身类型的引用,不同包的子类才能访问父类的protected成员(对应ee的情况)。

内容的提问来源于stack exchange,提问作者iwsnmw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 13:37:25