Java继承详解:同包与跨包场景下的成员访问规则
本文深入剖析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 分析跨包行为的结论
运行程序后,我们会发现:
say()和print()依然正常工作,因为它们是protected和public的。- 如果父类中有默认访问权限(无修饰符)的方法(如之前的
sum),在跨包子类中将不可见,导致编译错误。 private成员永远不可访问。
继承机制总结与最佳实践
通过上述代码实战,我们可以得出以下结论:
- 权限传递原则:子类继承成员后,该成员的访问权限保持不变。
public保持公开,protected保持受保护。 - 包的作用域:默认(friendly)修饰符严格依赖包路径。一旦跨包,除非使用反射,否则子类无法直接继承默认权限的字段和方法。
private的隔离性:私有的属性和方法不构成继承关系。子类无法直接引用它们,通常需要通过父类提供的getter/setter方法进行间接交互。- 方法重写(Override):在跨包继承中,重写父类的
protected方法是扩展功能的常用模式,确保子类能以自己的方式处理继承下来的状态。
以上就是Java继承及访问权限控制的详细内容,更多关于Java子类继承的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









