java中成员变量和类变量的访问权限由同一套修饰符控制,但因归属对象或类而表现不同:public、protected、private和默认修饰符语义一致;类变量推荐通过类名访问;实例变量应默认private并配getter/setter;protected是“家族协作权限”,子类可通过super或this访问,不可通过父类实例访问。

Java 中成员变量(实例变量)和类变量(静态变量)的访问权限,本质上由同一套修饰符控制,但因归属不同(对象 vs 类),实际可见性表现有差异。关键不是“能不能写”,而是“谁能在哪儿怎么用”。
四种修饰符的作用范围一致
public、protected、private 和默认(无修饰符)对成员变量和类变量语义完全相同:
-
public:任何类、任何包都能直接访问,如
obj.publicField或MyClass.publicStaticField -
protected:本类、同包类、不同包的子类可访问;注意:子类不能通过父类实例访问 protected 实例变量(
parentObj.protectedField编译报错),但可通过super.field或this.field直接使用 - private:仅声明它的那个类内部可用,子类和外部类均不可见,哪怕继承也无法绕过
- 默认(包级):仅限同包内类访问,与是否 static 无关;不同包的子类即使继承了该类,也看不到 default 成员
类变量访问要特别注意调用方式
类变量属于类本身,推荐始终通过类名访问,语义清晰且避免歧义:
- ✅ 推荐:
MyClass.count、MyClass.getInstance() - ⚠ 不推荐:
obj.count——语法虽允许,但易被误认为是实例变量;若后续在实例上动态添加同名字段,还会造成遮蔽 - ? private 类变量只能在本类中用
MyClass.privateStaticField访问;反射也不能绕过访问控制检查
成员变量应默认私有,靠 getter/setter 控制访问
实例变量描述对象状态,直接暴露风险高,实践中几乎总是:
- 声明为
private - 配套提供
public的 getter/setter 方法(如getName()、setName(String)) - 在 setter 中加入校验逻辑(比如年龄不能为负、邮箱格式校验),这是 private + 方法组合带来的真正控制力
protected 在继承场景中的真实行为
它不是“半公开”,而是“家族协作权限”:
- 同包子类:可通过
this.field或super.field直接访问 - 不同包子类:仍可通过
super.field访问(继承所得),但不能通过父类实例访问 - 类变量同理:protected static 字段对子类可见,但不同包子类以外的类无法访问
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











