Java类修饰符仅限public或默认,protected/private不可用于顶层类;成员变量四种修饰符语义统一,但访问受static/instance及继承关系影响,推荐一律private并配getter/setter。

Java 访问修饰符对类和成员变量的可见性规定并不完全一致,关键在于“谁可以访问”和“在哪儿访问”,而不是简单套用同一张表。
类本身的修饰符限制更严格
顶层类(即直接定义在 .java 文件里的类)只能用 public 或默认(无修饰符):
-
public class A:必须与文件同名,任何包都能通过new A()或A.staticMethod()使用 - 默认类(如
class B):仅本包内可实例化、继承或引用;不同包即使 import 也无法访问,也不能继承
protected 和 private 不能修饰顶层类,只可用于内部类。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
成员变量的四种修饰符语义统一,但使用效果因 static/instance 而异
所有修饰符对实例变量和静态变量都适用,权限范围一致,区别在于调用方式是否依赖对象:
public int x;
任何类都能访问:obj.x或MyClass.x
不推荐直接暴露,破坏封装protected int y;
本类、同包子类、不同包子类(通过this.y或super.y)可用
❌ 不能写parentObj.y(父类实例点调,编译报错)
✅ 子类中可直接读写y,无需 getterint z;(默认,包级)
同包内所有类(含非子类)可直接访问obj.z或MyClass.z
不同包子类无法访问,哪怕继承了该字段也不会出现在子类字段列表中private int w;
仅声明它的那个类内部可用(包括静态方法、实例方法、构造器)
子类、同包子类、外部类全部不可见,反射需setAccessible(true)才能绕过
一个容易忽略的关键细节protected 和默认修饰符看似都允许“同包访问”,但 protected 多出“跨包子类继承访问”这一条;而默认修饰符连跨包子类都不行——它不参与继承链,只是包内共享。
比如 Parent 类有个 default int count;,Child extends Parent 在不同包里,Child 内部不能用 count,编译失败。
实际建议
- 成员变量一律
private,配public的 getter/setter(需要控制逻辑时可加校验) - 工具类中的常量或缓存字段,用
static final+ 默认修饰符,限定包内协作 - 父类预留扩展点,才考虑
protected,且应明确文档说明“供子类重写或复用” - 避免
public字段,除非是public static final常量

















