Java继承详解:同包与跨包场景下的成员访问规则

Owen
Owen
发布时间:2026-10-14 | 5人浏览过
原创

本文深入剖析Java类继承的实现机制,详细对比同包与跨包两种环境下的成员变量与方法访问限制。通过完整的可运行代码示例,展示public、protected及默认包私有权限在子类继承中的行为差异,明确private不可被继承的铁律及方法重写注意事项。

继承的本质与访问控制基础

继承是面向对象编程中代码复用的核心手段。子类(Child Class)通过 extends 关键字获得父类(Parent Class)的成员。这里的“获得”并非简单的物理复制,而是语义上的包含:子类将其视为自己的成员变量和方法,可以直接通过实例进行操作和调用。

然而,继承的范围受到严格限制。Java中的四种访问修饰符决定了哪些成员真正被继承:

  • public:所有情况均可访问。
  • protected:本包内或不同包的子类中可以访问。
  • 默认(friendly/package-private):仅在同一包内可见。
  • private:绝对不继承,仅在父类内部可见。

第一步:构建并测试同包继承场景

当父类和子类位于同一包(Package)下时,除 private 外的所有成员(包括protected和默认访问权限的成员)均可被子类正常继承和使用。

1.1 定义父类

创建包含不同权限属性的父类 Parent.java。

package com.b510;

public class Parent {
    private int numbera = 10;
    protected int numberb = 20;

    // 默认访问权限(friendly)
    void sum() {
        numberb = numbera + numberb;
        System.out.println("sum method result: " + numberb);
    }

    // 私有方法
    private int getNumbera() {
        return numbera;
    }

    public void print() {
        System.out.println("print method: " + (numberb + numbera));
    }

    protected void say() {
        System.out.println("Hello, i'm parent class!");
    }
}

1.2 实现子类

创建子类 SubClass.java,尝试调用父类各成员。

package com.b510;

public class SubClass extends Parent {
    
    // 测试默认方法继承
    void youYuan() {
        System.out.println("子类可以访问numberb: " + numberb);
    }

    // 私有方法仅在本类有效
    private void priFun() {
        System.out.println("这是私有方法");
    }

    protected void proFun() {
        System.out.println("protected方法: " + numberb);
    }
}

1.3 验证执行结果

在主类中实例化子类并调用其继承来的方法及自身方法。注意:getNumbera() 因是 private 且无法直接操作 numbera,故不在调用列表中。

package com.b510;

public class ParentAndSubClass {
    public static void main(String[] args) {
        SubClass sub = new SubClass();
        sub.say();       // 继承自父类 protected
        sub.sum();       // 继承自父类 default
        sub.print();     // 继承自父类 public
        sub.proFun();    // 子类自身
        sub.youYuan();   // 子类自身,调用了继承的 numberb
    }
}

执行输出预期为:
Hello, i'm parent class!
30(sum计算结果)
numberb+numbera=30(实际应为10+20,此处根据代码逻辑显示)...

第二步:重构并测试跨包继承场景

将父类移出包边界,观察默认访问权限(default/friendly)在继承中的作用变化。

2.1 修改父类包路径

将父类 Parent 移至 com 包下,而子类仍保留在 com.b510 包。

// Parent.java 文件位置变更
package com; // 不再是 com.b510

public class Parent {
    private int numbera = 10;
    protected int numberb = 20;
    // ... 其他方法保持不变 ...
}

2.2 调整子类以支持继承

在 SubClass.java 中必须添加导入语句,并重写 say() 方法来演示多态性。

package com.b510;

import com.Parent; // 引入跨包父类

public class SubClass extends Parent {
    @Override
    protected void say() {
        // 依然可以访问继承过来的 protected numberb
        System.out.println("重写的say: numberb=" + numberb);
    }

    void youYuan() {
        // 注意:此处无法编译如果尝试访问父类的非public/non-protected成员
        System.out.println("youYuan executed");
    }
}

2.3 分析跨包行为的结论

运行程序后,我们会发现:

  1. say() 和 print() 依然正常工作,因为它们是 protected 和 public 的。
  2. 如果父类中有默认访问权限(无修饰符)的方法(如之前的 sum),在跨包子类中将不可见,导致编译错误。
  3. private 成员永远不可访问。

继承机制总结与最佳实践

通过上述代码实战,我们可以得出以下结论:

  • 权限传递原则:子类继承成员后,该成员的访问权限保持不变。public 保持公开,protected 保持受保护。
  • 包的作用域:默认(friendly)修饰符严格依赖包路径。一旦跨包,除非使用反射,否则子类无法直接继承默认权限的字段和方法。
  • private 的隔离性:私有的属性和方法不构成继承关系。子类无法直接引用它们,通常需要通过父类提供的 getter/setter 方法进行间接交互。
  • 方法重写(Override):在跨包继承中,重写父类的 protected 方法是扩展功能的常用模式,确保子类能以自己的方式处理继承下来的状态。

以上就是Java继承及访问权限控制的详细内容,更多关于Java子类继承的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表