SpringBoot中@NotNull/@NonNull注解字段Setter操作与空指针疑问
问题1:在SpringBoot中,被@NotNull注解标注的HTTP请求对象字段,能否在Setter方法中访问并操作且不抛出空指针异常?
先明确:你用的是JSR-380的@javax.validation.constraints.NotNull验证注解,它的作用是在参数验证阶段检查字段是否为null,但管不住Setter方法的执行时机。
SpringBoot默认流程是:先通过Setter把请求里的值(哪怕是null)赋值给对象字段,之后才会触发@Valid/@Validated驱动的验证逻辑。
举个例子,如果请求传入的userId是null:
- 首先
setUserId(null)会被执行,把null赋值给userId字段; - 之后验证逻辑才会发现
userId违反了@NotNull约束,抛出ConstraintViolationException。
如果你的Setter里要对这个字段做操作(比如假设userId的Setter里写了this.userId = userId.longValue();),那传入null时,Setter执行时就会直接抛出NPE,根本轮不到验证注解生效。
总结:@NotNull不保证Setter里的字段非null,要避免NPE,要么在Setter里加null判断,要么自定义逻辑让验证在Setter执行前触发(默认做不到)。
问题2:被@NotNull注解标注的字符串字段是否可在Setter方法中执行trim操作?若请求传入revTag为null(该字段标注@NotNull且Setter中调用trim),是否会抛出空指针异常?此场景下会发生什么?
当然可以在Setter里做trim,但前提是传入的值不为null。
如果请求传入revTag为null,流程是这样的:
- Spring先调用
setRevTag(null),此时null.trim()会直接抛出NullPointerException; - 这个NPE会比
@NotNull的验证异常更早触发,程序直接报错,根本走不到验证阶段。
这显然不符合预期——我们希望先验证字段非null,再做trim。解决方法很简单,在Setter里加null判断:
public void setRevTag(final String revTag) { this.revTag = revTag != null ? revTag.trim() : null; }
这样即使传入null,Setter也不会抛NPE,之后@NotNull的验证逻辑会正常生效,抛出约束违反的异常,更符合验证的设计意图。
问题3:未标注@NotNull的resNote字段若传入null,调用trim时必然抛出空指针异常,是否属实?
完全属实!因为resNote没有@NotNull注解,意味着这个字段允许为null,Spring会直接把请求里的null值传给setResNote方法,而你的Setter里直接调用resNote.trim(),null调用方法肯定会抛NPE,没有任何验证逻辑会阻止这个操作。
要修复的话,同样在Setter里加null判断即可:
public void setResNote(final String resNote) { this.resNote = resNote != null ? resNote.trim() : null; }
这样即使传入null,字段会被赋值为null,不会触发NPE,也符合字段允许为null的设计。
内容的提问来源于stack exchange,提问作者John Doe

