以前一直在某些代码中看到过使用@Nullable 标注过的注释,当时也没有在乎究竟是什么意思,因此这篇文章来谈谈Spring中关于Null的那些事。java
在Java中不容许让你使用类型表示其null的安全性,但Spring Framework 如今在org.sprinngframework.lang包提供如下注释,以便声明API和字段的可空性:spring
@Nullable
: 用于指定参数、返回值或者字段能够做为null的注释。@NonNull
: 与上述注释相反,代表指定参数、返回值或者字段不容许为null。(不须要@NonNullApi和@NonNullFields适用的参数/返回值和字段)@NonNullApi
: 包级别的注释声明非null做为参数和返回值。@NonNullFields
:包级别的注释声明字段默认非空Spring Framework 自己利用了上面这几个注释,但它们也能够运用在任何基于Spring的Java 项目中,以声明空安全api 和 空安全字段。还没有支持泛型和数组元素的可空性,但应也即将发布在后来的版本。Spring Null-Safety出如今Spring5中,让咱们更方便的编写空安全的代码,这叫作null-safety,null-safety不是让咱们逃脱不安全的代码,而是在编译时产生警告。 此类警告能够在运行时防止灾难性空指针异常(NPE)。api
@NonNull注释是null-safety的全部注释中最重要的一个,咱们可使用此注释在指望对象引用的任何地方声明非空约束:字段、方法参数或者方法返回值。数组
先来看一个例子安全
public class Student { private String name; public String getName() { return name; } public void setName(String name) { if(name != null && name.isEmpty()){ name = null; } this.name = name; } }
上述代码对name的校验是有效的,可是存在一个缺陷,若是name被设置为null的话,那么当咱们使用name的时候,就会以NullPointerException来结尾。eclipse
使用@NonNullide
Spring 的null-safety特性可以容许idea
或者eclipse
报告这个潜在的威胁,例如,若是咱们用IDEA对属性加上@NonNull会出现以下的效果。工具
奇怪,并无什么变化啊,没看见有潜在的安全提示啊,那是由于你没有在idea进行设置性能
若是你也没有提示的话,能够经过以下的方式设置安全检查开发工具
若是还很差使的话,那就在右侧 configuration annotations 添加一下 @NonNull和 @Nullable 所在的jar包,以下:
添加上,打上 ✅ 便可看到以下效果。
如今fullName 已经被@NonNull 注释添加编译器检查null值的功能了!
若是你不相信的话,能够把@NonNull 注释去掉,你的鼠标再放在fullName 上,已经没有这句提示了。
@NonNull 注解可以帮助你确保null-safety。然而,若是此注释直接装饰全部的字段的话,就会污染整个代码库。
Spring提供了另一个不容许为null的注解 — @NonNullFields
。这个注解适合用在包级别上,通知咱们的开发工具注释包中全部的字段,默认的,不容许为null
新建一个Parent类,并在该类所属包下建立一个名为package-info.java
的类,建立的不是Java类,而是建立的file
,名为package-info.java,以下
package-info.java
@NonNullFields package com.nullsafety.demo.pojo; import org.springframework.lang.NonNullFields;
新建一个Parent.java
类
public class Parent { private String son; private String age; private String name; public void setSon(String son) { if(son != null && son.isEmpty()){ son = null; } this.son = son; } public void setAge(String age) { if(age != null && age.isEmpty()){ age = null; } this.age = age; } public void setName(String name) { if(name != null && name.isEmpty()){ name = null; } this.name = name; } }
package-info.java 中的
@NonNullFields
可以对Parent类中全部的属性起做用,把鼠标放在任意一个属性上,会出现编译期检查的提示
@NonNullFields注释一般比@NonNull更好,由于它有助于减小样板。 可是,有时咱们想要从包级别指定的非null约束中免除某些字段,这时候就会使用到@Nullable
注解
改造一下Person.java,Person.java 与pack-info.java 处于同一包下
public class Person { @NonNull private String fullName; @Nullable private String nickName; public String getNickName() { return nickName; } public void setNickName(String nickName) { if(nickName != null && nickName.isEmpty()){ nickName = null; } this.nickName = nickName; } public String getFullName() { return fullName; } public void setFullName(String fullName) { if(fullName != null && fullName.isEmpty()){ fullName = null; } this.fullName = fullName; } }
在这种状况下,咱们使用@Nullable注释来覆盖字段上@NonNullFields的语义。
@NonNullFields
注释仅适用于其名称所示的字段。 若是咱们想对方法的参数和返回值产生相同的影响,咱们须要@NonNullApi。
添加 @NonNullApi和 @NonNullFields 在 configure annotations 中,并选用NonNullApi
与@NonNullFields同样,咱们须要在package-info.java 中定义@NonNullApi
package-info.java
@NonNullApi @NonNullFields package com.nullsafety.demo.pojo; import org.springframework.lang.NonNullApi; import org.springframework.lang.NonNullFields;
加上以下注释后的效果以下: 能够在返回值的时候接受到编译期的提示。
后记:
看完文章,你至少应该了解
欢迎关注