包结构与访问权限是封装思想的内外两面:包定义协作边界,权限修饰符决定边界内通信方式;推荐com.公司名.系统名.模块名.层级名四级结构,按语义分层建包,default权限为包内协作主力,private保障字段安全,public仅用于api/spi契约。

包结构设计和访问权限不是两套独立规则,而是同一封装思想的内外两面:包定义协作边界,权限修饰符决定边界内如何通信。设计得当,代码自然清晰、低耦合、易演进。
按语义分层建包,让包名自带契约
包名不是目录别名,而是模块职责的声明。推荐采用 com.公司名.系统名.模块名.层级名 的四级结构,其中最后一级体现访问意图:
-
api:只放 public 类和接口,对外提供稳定入口,如
OrderService -
spi:放 public 接口 + default 回调类,供插件扩展,如
PaymentProvider(public)与PaymentHook(default) -
impl 或 internal:大量使用默认权限,存放 DTO、Builder、工具方法、内部事件类,如
OrderBuilder、AmountParser - model 或 entity:实体类用 private 字段 + public getter/setter,避免直接暴露状态
用默认权限(不写修饰符)构建高内聚协作单元
默认权限是包内协作最自然、最可靠的机制——编译期强制可见,比注释更可信,比反射更安全:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 把强关联类(如订单校验、库存扣减、支付适配)统一放进
com.example.order包,它们共用的解析逻辑AmountParser.parse()设为 default,同包可调,跨包连编译都过不去 - 构建器中的中间状态字段(如
OrderBuilder.state)设为 default,包内流程自由流转,外部无法构造半成品对象 - 内部发布器类
InternalEventPublisher不加 public,外部连 import 都失败,彻底杜绝误用
警惕包结构失配导致的权限失效
默认权限的效果高度依赖物理结构与运行时环境,常见陷阱需主动规避:
- 两个 Maven 模块各自定义了
com.example.service,只要最终 classpath 合并,它们仍能互相访问 default 成员——应确保关键包名全局唯一,或启用 JPMS(module-info.java)强化隔离 - 避免把 default 工具类扔进通用包(如
com.example.common),等于向所有同包类开放,失去控制意义 - 若某方法仅限包内特定几个类使用,建议加命名后缀(如
XXXInternal)并用 Javadoc 明确标注“仅限本包协作”
权限修饰符与包协同的典型组合
四种修饰符不是孤立选择,而要结合包位置判断实际可见范围:
- public:只用于 api 层契约类、SPI 接口、框架必需入口,一个文件最多一个 public 类,且文件名必须匹配
- protected:适合父类中希望被子类继承重写、但不希望被无关类调用的方法;注意不同包子类只能访问自身继承来的 protected 成员,不能访问父类其他实例的该成员
- default:包内协作主力,适用于工具方法、内部状态、构建逻辑、事件总线等——它是封装的第一道也是最有效的一道屏障
- private:字段和辅助方法优先设为 private,配合 getter/setter 控制读写逻辑,这是封装的根基
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










