Java访问权限修饰符详解:成员变量与方法的作用域规则
在Java开发中,合理设置成员变量和方法的访问权限是封装性的核心体现。许多开发者容易混淆不同修饰符在“同包”与“跨包”、“本类”与“子类”之间的具体作用域。本文将结合代码实测结果,总结 public、protected、default(默认)和 private 的具体访问规则。
Java访问权限的核心逻辑
Java提供了四种可见性级别,从宽到窄依次为:public → protected → default(无修饰符)→ private。理解它们的关键在于区分两个维度:
- 包(Package)维度:类是否位于同一个包下。
- 继承(Inheritance)维度:访问者是否是当前类的子类。
详细规则对照表
为了直观展示各修饰符的影响范围,我们可以将情况分为两大类进行观察。
1. 非继承关系下的访问权限
当我们在其他类中直接实例化并访问某个对象的成员时,权限规则如下:
| 访问场景 | public | protected | default (空) | private |
| 自己包 · 自己类 | ✅ 可访问 | ✅ 可访问 | ✅ 可访问 | ✅ 可访问 |
| 自己包 · 其他类 | ✅ 可访问 | ✅ 可访问 | ✅ 可访问 | ❌ 不可访问 |
| 别的包 · 其他类 | ✅ 可访问 | ❌ 不可访问 | ❌ 不可访问 | ❌ 不可访问 |
2. 继承关系下的访问权限
当子类继承了父类,并在子类内部或外部通过子类实例访问其继承来的成员时,规则发生变化(主要影响 protected 和 default):
| 访问场景 | public | protected | default (空) | private |
| 自己包 · 子类 | ✅ 可访问 | ✅ 可访问 | ✅ 可访问 | ❌ 不可访问 |
| 别的包 · 子类 | ✅ 可访问 | ✅ 可访问* | ❌ 不可访问 | ❌ 不可访问 |
注:protected 在“别的包·子类”场景中,仅能在子类自身代码范围内(如方法体内)直接访问该成员,无法像 public 那样通过子类实例对象访问(即 child.protectedField 会编译报错)。
代码实测验证
以下是针对上述规则的源码验证。我们在 com.jaovo 包定义了测试主类,包含四个基础类演示不同访问效果。
package com.jaovo;
import cn.jaovo.D;
import cn.jaovo.E;
// 继承关系演示:这里继承 cn.jaovo 包下的 E 类
public class Chengyuan extends E {
public static void main(String[] args) {
// --------------------------------------------------
// 一、成员变量权限验证
// --------------------------------------------------
// 1. 同一包内的其他类访问 (实例化 B)
/*
B b = new B();
System.out.println(b.i1); // ✅ public
System.out.println(b.i2); // ✅ default
// System.out.println(b.i3); // ❌ compile error: private
System.out.println(b.i4); // ✅ protected
*/
// 2. 跨包的类访问 (实例化 D,位于 cn.jaovo)
/*
D d = new D();
System.out.println(d.i1); // ✅ public
// System.out.println(d.i2); // ❌ compile error: default
// System.out.println(d.i3); // ❌ compile error: private
System.out.println(d.i4); // ❌ compile error: protected (跨包非私有访问)
*/
// 3. 跨包包子类访问 (继承自 E,E与D同类定义)
Chengyuan ch = new Chengyuan();
System.out.println(ch.i1); // ✅ public
// System.out.println(ch.i2); // ❌ default 跨包不可见
// System.out.println(ch.i3); // ❌ private
System.out.println(ch.i4); // ⚠️ protected 虽然继承了,但作为外部实例不能直接访问受保护字段
// (注意:在Chengyuan的方法体内可以直接用this.i4,但不能用ch.i4)
// --------------------------------------------------
// 二、成员方法权限验证
// --------------------------------------------------
// 方法与变量的权限表现一致
/*
B b = new B();
System.out.println(b.m1()); // ✅
System.out.println(b.m2()); // ✅
// System.out.println(b.m3()); // ❌
System.out.println(b.m4()); // ✅
*/
// 跨包方法调用
System.out.println(ch.m1()); // ✅
// System.out.println(ch.m2()); // ❌
// System.out.println(ch.m3()); // ❌
System.out.println(ch.m4()); // ✅ (子类继承了方法,可以通过父类引用/子类引用调用)
}
}
// 定义在本包的基础类
/*
class B {
public int i1 = 1;
int i2 = 2;
private int i3 = 3;
protected int i4 = 4;
public int m1() { return 1; }
int m2() { return 1; }
private int m3() { return 1; }
protected int m4() { return 1; }
}
*/
// --------------------------------------------------------
// cn.jaovo 包中的 D 和 E (此处模拟跨包环境)
package cn.jaovo;
public class D {
public int i1 = 1;
int i2 = 2;
private int i3 = 3;
protected int i4 = 4;
public int m1() { return 1; }
int m2() { return 1; }
private int m3() { return 1; }
protected int m4() { return 1; }
}
public class E {
public int i1 = 1;
int i2 = 2;
private int i3 = 3;
protected int i4 = 4;
public int m1() { return 1; }
int m2() { return 1; }
private int m3() { return 1; }
protected int m4() { return 1; }
}
关键注意点总结
- Protected 的特殊性:它允许“跨包子类访问”,但这指的是子类可以继承并调用它,而不是任意跨包对象都能拿到它的值。
- Default 的边界:一旦脱离了包的范围,无论是否有继承关系,
default成员都不可见。 - 封装原则:通常情况下,成员变量推荐使用
private并通过 getter/setter 暴露;业务方法根据复用需求选择public或protected。
以上就是Java中成员变量与方法访问权限修饰符的详细解析与代码验证,更多关于Java基础语法与面向对象设计的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









