默认访问权限在同包内完全开放:同一运行时包下所有类(无论源文件、模块或继承关系)均可直接访问,默认权限由JVM运行时包名和类加载器决定,非源码路径;反射在同包内也可绕过限制。

Java 中包访问权限(即不写任何修饰符的默认权限)在同一个包内是完全开放的:只要类、方法或字段声明为默认权限,同一包下的所有类——无论是否继承关系、是否在同一个源文件、是否属于不同 Maven 模块——都能直接访问。
同一包内哪些情况可以互访
只要满足“运行时包名完全一致”,就构成有效的同包关系:
- 不同 .java 文件,但 package 声明相同(如都写
package com.example.utils;),可互相调用默认方法、访问默认字段 - 一个文件里定义多个类(例如主类 + 静态内部工具类),它们天然同包,彼此能自由使用默认成员
- 多模块项目中,即使
com.example.service分散在 module-a 和 module-b,只要最终 classpath 合并、类加载器加载到同名包,就视为同包,可互访 - 子类与父类在同一包时,子类可以直接使用父类的默认字段和方法(无需
protected或public)
容易被忽略的关键细节
默认权限不是靠源码位置或项目结构判断,而是由 JVM 运行时的包名和类加载器共同决定:
- IDE 编译时报错 “cannot find symbol”,但运行时却能成功调用——很可能是 classpath 合并导致包连通了
- 模块系统(JPMS)未启用时(如没写
module-info.java),默认权限行为完全依赖传统类路径规则 - 反射访问同包内的默认成员是允许的:
field.setAccessible(true)在同包下不会抛异常,可直接读写
怎么用才符合设计意图
默认权限本身不带语义,要让它真正起到控制作用,得配合包命名和职责划分:
立即学习“Java免费学习笔记(深入)”;
- 把强耦合协作的类放进带后缀的包名里,比如
com.example.order.internal,只在这里用默认成员 - 避免在通用包(如
com.example.common)里暴露默认方法,否则等于向整个项目开放 - 对仅限本包特定类使用的成员,加命名约定(如
parseHelperInternal())并配 Javadoc 注明“仅限本包” - 不要指望默认权限阻止反射——它只拦编译期和常规调用,不提供运行时安全防护


















