封装需校验+default限包内+protected慎用字段+public精简且防御返回。private仅阻直访,须在构造器/setter校验;default适合同包协作;protected字段易破封装,应代以方法;public接口须最小化并防御性返回。

private 是封装起点,但必须配校验逻辑
把字段声明为 private 只是封住直接访问通道,并不等于数据自动安全。比如 private int age; 若只在 setAge(int) 里简单赋值,外部仍可传入 -5 或 300 这类非法值,对象就处于非法状态。
所有初始化入口都要做校验:构造器、setter 方法都得检查范围、非空、格式等。校验失败明确抛出 IllegalArgumentException,例如:if (age 150) throw new IllegalArgumentException("age must be between 0 and 150");
default 权限适合包内高内聚协作
不加修饰符的 default(包级私有)天然适用于同一业务包内的协作。比如订单模块中 Order、OrderItem、Payment 都在 com.example.order 包下,它们之间可共享中间计算字段或工具方法,但对外部包完全不可见。
- 跨包调用时,default 成员编译直接报错,边界清晰
- 比
public更轻量,比private更灵活,适合模块内部解耦 - 别为了“省事”把本该 private 的字段改成 default,那是在暴露实现细节
protected 字段要慎用,优先暴露方法
protected 让子类能访问字段,但也意味着父类的实现细节会泄漏。例如父类有个 protected List<string> tags;</string>,子类可能直接 tags.add("new"),破坏父类对集合状态的控制。
- 尽量用
protected void addTag(String tag)这类方法代替 protected 字段 - 若必须暴露集合,getter 返回不可修改视图:
Collections.unmodifiableList(tags) - 子类不该依赖父类字段名或类型,而应通过受控方法交互
public 接口要精简,且带防御性返回
public 方法是外界唯一合法入口,每个都是数据守门人。不要为每个 private 字段机械生成 getter/setter——只暴露真正需要被读写的属性。
- 返回可变对象(如
ArrayList、Date、BigDecimal)时,必须做防御性拷贝或返回不可修改包装 -
getBalance()不能返回原始引用,否则外部可篡改内部状态 -
setName(String)要拒绝 null 或空白字符串,setEmail(String)可加基础格式验证
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











