继承父类时重写成员变量并添加注解的实现方式及替代方案咨询
关于继承父类后为成员变量添加注解的实现问题
首先明确:Java中成员变量无法被重写
你给出的代码里,子类validateAddress中定义的private Integer postalCode并不是重写父类的同名变量,而是子类自己新增的一个独立变量。因为父类的postalCode是私有访问权限,子类无法直接访问父类的该变量,所以子类的同名变量和父类的变量完全是两个不同的字段。这种写法会导致:
- 父类中如果有操作
postalCode的方法,只会操作父类自己的字段,子类的注解完全不会对其生效 - 子类内部如果直接使用
postalCode,访问的是自己的字段,和父类无关,逻辑容易混乱
可行的替代方案
方案1:重写Getter方法并添加注解(推荐)
如果可以修改父类,先把父类的字段访问权限改为protected,然后在子类中重写对应的Getter方法,将注解添加到Getter上。大部分验证框架(如Hibernate Validator)支持识别Getter上的注解来验证字段:
public class Address { protected Integer postalCode; public Integer getPostalCode() { return postalCode; } } public class ValidateAddress extends Address { @Override @NotNull @Valid public Integer getPostalCode() { return super.getPostalCode(); } }
方案2:使用组合而非继承
如果不能修改父类,或者继承关系不合适,可以采用组合的方式,将父类作为子类的成员变量,然后在子类中对该成员变量或其Getter添加注解:
public class ValidateAddress { @NotNull @Valid private Address address; public Integer getPostalCode() { return address.getPostalCode(); } }
方案3:自定义验证器
如果以上方案都不适用,可以编写自定义的验证注解和验证器,针对子类的逻辑手动校验postalCode的合法性:
// 自定义验证注解 @Target({TYPE}) @Retention(RUNTIME) @Constraint(validatedBy = ValidateAddressValidator.class) public @interface ValidAddress { String message() default "Postal code cannot be null"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; } // 验证器实现 public class ValidateAddressValidator implements ConstraintValidator<ValidAddress, ValidateAddress> { @Override public boolean isValid(ValidateAddress address, ConstraintValidatorContext context) { // 这里根据实际逻辑获取postalCode并校验 return address.getPostalCode() != null; } } // 使用注解 @ValidAddress public class ValidateAddress extends Address { // 原有代码 }
内容的提问来源于stack exchange,提问作者Akhdan Rasiq
相关产品推荐
相关产品推荐

