成员变量和类变量的访问控制取决于访问修饰符而非存储位置,二者均受public、protected、private、默认四种修饰符约束;修饰符语义一致,但因生命周期与归属不同导致实际访问效果差异。

成员变量和类变量的访问控制,核心在于“谁可以读、谁可以改”,而不是“存哪儿”或“怎么用”。两者都受同一套访问修饰符约束,但因生命周期和归属不同,实际效果有差异。
四种访问修饰符的作用范围一致
无论变量是实例变量(成员变量)还是静态变量(类变量),public、protected、private、默认(包级)这四种修饰符的语义完全相同:
-
public:任何类、任何包都能直接访问(如
obj.publicField或MyClass.publicStaticField) - protected:本类、同包类、不同包的子类可访问(注意:子类不能通过父类实例访问 protected 实例变量,但可通过继承关系直接使用)
- private:仅限声明它的那个类内部使用,子类和外部类均不可见
- 默认(无修饰符):仅限同包内的类访问,与是否为 static 无关
类变量访问需注意调用方式
类变量属于类本身,推荐通过类名访问,这样语义清晰且避免歧义:
- 正确写法:
MyClass.count、MyClass.getInstance()(静态方法同理) - 不推荐:
obj.count——虽然语法允许,但容易让人误以为是实例变量;若后续在实例上动态添加同名字段,还会造成遮蔽 - private 类变量只能在本类中通过类名访问,外部即使反射也受限于访问控制检查
成员变量强调封装,通常设为 private
实例变量描述对象状态,直接暴露风险高。实践中几乎总是:
- 声明为 private
- 配套提供 public 的 getter/setter 方法(如
getName()、setName(String)) - 在 setter 中加入校验逻辑(比如年龄不能为负),这是 private + 方法组合带来的控制力
- 子类无法绕过 private 实例变量的封装,哪怕继承了该类,也不能直接访问父类的 private 字段
特殊情况:protected 成员变量在继承中的表现
如果一个实例变量被声明为 protected,子类可以直接使用它(无需 getter),但前提是:
- 子类与父类在同包 → 可以通过
this.field或super.field访问 - 子类在不同包 → 仍可通过
super.field访问(继承所得),但不能通过父类实例访问(如parentObj.protectedField会编译报错) - 类变量同理,protected static 字段对子类可见,但外部包非子类不可见











