封装在java中关键依赖包机制:默认权限(无修饰符)实现包级访问控制,是封装的第一道结构边界;包名映射业务职责,如order.entity、order.service、order.internal通过物理组织明确访问范围,配合private字段、public接口与默认权限工具类协同实现分层封装。

封装在 Java 中不只是靠 private 字段加 public 方法,更关键的是借助包(Package)这一层级结构,把“谁该看到什么”从物理组织上定下来。包不是文件夹别名,它是访问控制的第一道边界——默认权限(即不写修饰符)只对同包类开放,这就让封装有了结构支撑。
用包名映射业务职责,自然形成访问边界
包名不是随便起的,它要反映模块职能和调用关系。比如:
-
com.example.order.entity:只放Order、OrderItem这类纯数据类,字段全private,提供标准 getter/setter;不暴露构造逻辑或校验细节 -
com.example.order.service:放业务逻辑类,方法设为public,但只对 controller 或其他 service 开放;内部工具类或辅助方法可用默认权限,限制在本包内复用 -
com.example.order.internal:专放不对外承诺的实现类(如缓存适配器、临时转换器),类本身不加public,连同其成员都用默认权限——外部包根本看不到它们
默认权限(package-private)是封装最常用的“软隔离”手段
不写任何修饰符的类、方法、字段,天然只能被同包类访问。它比 private 宽松,又比 protected 严格,适合包内协作场景:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 一个工具类
JsonUtils放在com.example.common.util包中,方法声明为static String toJson(Object obj)(无修饰符),那么只有该包下的类能直接调用;其他模块必须走public接口或依赖注入 - 实体类中的校验逻辑可抽成默认方法,如
User类里boolean isValidEmail(String e),仅供同包的UserBuilder或UserValidator使用,避免被误调或滥用
跨包调用必须显式暴露,且优先用 public 接口而非具体类
不同包之间不能依赖默认权限成员,这倒逼你思考“哪些能力真该公开”:
- controller 包调用 service 包,应依赖
UserService接口(public interface),而不是它的实现类DefaultUserService(可设为默认权限类) - DAO 层返回的数据对象,如果只供 service 包使用,就不要放在
model这种通用包里,而是放在service.dao子包下,并用默认权限声明——这样 controller 就无法意外引用到 DAO 内部结构 - 避免在公共包(如
api或dto)中暴露带业务逻辑的方法;DTO 类字段通常public final或配private+publicgetter,不提供行为
注意 protected 的真实作用范围,别误以为是“子类通用通行证”
protected 成员虽可在不同包子类中访问,但有重要限制:
- 子类能访问的是“继承来的”成员,不是父类其他实例的同名成员。例如
AdminUser extends User可以调用this.updatePassword(),但不能写new User().updatePassword() - 如果希望某功能既被子类继承使用,又被同包其他类调用,应改用默认权限 + 提取为包级工具类,而不是依赖
protected - 跨包继承在大型项目中往往意味着耦合加深,不如用组合+接口方式替代,把
protected留给真正需要继承扩展的少数核心抽象
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










