抽象类属性设计需明确“谁用、怎么用、何时初始化”:优先protected供子类复用,private封装内部状态,禁用public;必在构造方法中初始化,关键字段用final+传参,合理默认值可声明时赋值;仅放通用字段,专属状态由子类定义;配合模板方法在流程骨架中校验与使用属性。

抽象类中定义属性,核心是明确“谁用、怎么用、何时初始化”,不是随便加字段就完事。属性该用 protected 还是 private,要不要带默认值,是否允许子类直接访问或修改——这些决定直接影响后续子类的可控性和系统健壮性。
属性访问权限要匹配设计意图
抽象类的属性通常服务于子类共用逻辑,因此多数情况下应声明为 protected,而非 public 或 private:
-
protected:子类可直接访问和继承,便于复用(如
protected String name;),也方便在抽象方法中被统一使用; - private:仅限抽象类内部使用,适合封装仅由抽象类自身管理的状态(例如缓存标记、内部计数器);
- public 应避免——破坏封装,让子类随意修改可能破坏流程一致性;
- 不写访问修饰符(默认包级)一般也不推荐,限制了跨包继承的灵活性。
构造方法中完成属性初始化
抽象类虽不能实例化,但它的构造方法会被子类 super() 调用。所有必需的属性应在构造方法中传入并赋值,避免子类遗漏初始化或设为默认值(如 0 或 null)引发空指针或业务异常:
- 例如订单抽象类:
protected final double amount;声明为 final + 构造传参,确保金额不可变且必填; - 若属性有合理默认值(如状态字段),可在声明时直接初始化:
protected OrderStatus status = OrderStatus.CREATED;; - 避免在抽象类中留空属性(如
protected String id;不赋值),除非明确由子类自行设置并校验。
区分“共享状态”与“子类专属状态”
抽象类定义的属性,应属于整个类体系的公共上下文,不是为某个子类量身定制的:
- 适合放:名称、编号、创建时间、基础配置、校验规则参数等通用字段;
- 不适合放:会员等级折扣率、物流类型编码等只在特定子类中才有意义的字段——这类应由具体子类自己定义;
- 如果某属性仅被部分子类使用,考虑是否应提取为接口或通过策略模式解耦,而不是硬塞进抽象类。
配合模板方法控制属性使用时机
属性常与模板方法协同工作。抽象类用 final 方法 定义流程骨架,内部调用抽象方法前,确保关键属性已就位:
- 例如
process()方法中先调用validate()校验amount > 0,再执行calculateDiscount(); - 这样就把属性的合法性检查收口在抽象层,子类无需重复判断,也无法绕过;
- 属性一旦被模板方法依赖,就要在构造阶段强制提供,而不是靠子类“自觉”设置。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











