我赌你不清楚Spring中关于Null的这些事

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> 我赌你不清楚Spring中关于Null的这些事

点击上方“Java知音”,选择“置顶公众号”

技术文章第一时间送达!

阅**(点击即可跳转阅读)**

1. 

****2. ****

3. 

****4. ****

之前一直在某些代码中看到过使用@Nullable 标注过的注释,当时也没有在意到底是什么意思,之后忍不住去调查一番,这篇文章来谈谈Spring中关于Null的那些事。

在Java中不允许你使用类型表示其null的安全性,但Spring Framework 现在在org.sprinngframework.lang包提供以下注释,以便声明API和字段的可空性:

  • `@Nullable`: 用于指定参数、返回值或者字段可以作为null的注释。
  • `@NonNull`: 与上述注释相反,表明指定参数、返回值或者字段不允许为null。(不需要@NonNullApi和@NonNullFields适用的参数/返回值和字段)
  • `@NonNullApi`: 包级别的注释声明非null作为参数和返回值。
  • `@NonNullFields`:包级别的注释声明字段默认非空
  • @NonNull: 与上述注释相反,表明指定参数、返回值或者字段不允许为null。(不需要@NonNullApi和@NonNullFields适用的参数/返回值和字段)

    @NonNullFields:包级别的注释声明字段默认非空

    Spring Framework 本身利用了上面这几个注释,但它们也可以运用在任何基于Spring的Java 项目中,以声明空安全api 和 空安全字段。尚未支持泛型和数组元素的可空性,但应该也会在后期版本中支持这俩。

    Spring Null-Safety出现在Spring5中,让我们更方便的编写空安全的代码,这叫做null-safety,null-safety不是让我们逃脱不安全的代码,而是在编译时产生警告。 此类警告可以在运行时防止灾难性空指针异常(NPE)。

    @NonNull

    @NonNull注释是null-safety的所有注释中最重要的一个,我们可以使用此注释在期望对象引用的任何地方声明非空约束:字段、方法参数或者方法返回值。

    先来看一个例子

    
    public class Student {
    
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            if(null != null && name.isEmpty()){
                name = null;
            }
            this.name = name;
        }
    }
    

    上述代码对name的校验是有效的,但是存在一个缺陷,如果name被设置为null的话,那么当我们使用name的时候,就会以NullPointerException来结尾。

    使用@NonNull

    Spring 的null-safety特性能够允许idea或者eclipse报告这个潜在的威胁,例如,如果我们用IDEA对属性加上@NonNull会出现如下的效果。

    我赌你不清楚Spring中关于Null的这些事

    奇怪,并没有什么变化啊,没看见有潜在的安全提示啊,那是因为你没有在idea进行设置。

    设置安全检查

    如果你也没有提示的话,可以通过如下的方式设置安全检查:

    我赌你不清楚Spring中关于Null的这些事

    如果还不好使的话,那就在右侧 configuration annotations 添加一下 @NonNull和 @Nullable 所在的jar包,如下:

    我赌你不清楚Spring中关于Null的这些事

    添加上,打上 ✅ 即可看到如下效果。

    我赌你不清楚Spring中关于Null的这些事

    现在fullName 已经被@NonNull 注释添加编译器检查null值的功能了!

    测试一下,可以把@NonNull 注释去掉,你的鼠标再放在fullName 上,就没有这句提示了。

    @NonNullFields

    @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类中所有的属性起作用,把鼠标放在任意一个属性上,会出现编译期检查的提示

    我赌你不清楚Spring中关于Null的这些事

    @Nullable

    @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的语义。

    @NonNullApi

    @NonNullFields注释仅适用于其名称所示的字段。 如果我们想对方法的参数和返回值产生相同的影响,我们需要@NonNullApi。

    添加 @NonNullApi和 @NonNullFields 在 configure annotations 中,并选用NonNullApi

    我赌你不清楚Spring中关于Null的这些事

    与@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;
    

    加上如下注释后的效果如下: 可以在返回值的时候接受到编译期的提示。

    我赌你不清楚Spring中关于Null的这些事

    结语

    看完文章,你至少应该了解@NonNull, @Nullable, @NonNullFields, @NonNullApi四个注解和各自的作用范围以及如何设置编译期的Null-safety检查。

    看完本文有收获?请转发分享给更多人

    我赌你不清楚Spring中关于Null的这些事

    原文始发于微信公众号(Java知音):

    本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

    本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

    原文链接:blog.ouyangsihai.cn >> 我赌你不清楚Spring中关于Null的这些事


     上一篇
    Spring 动态切换、添加数据源实现以及源码浅析 Spring 动态切换、添加数据源实现以及源码浅析
    点击上方“Java知音”,选择“置顶公众号” 技术文章第一时间送达! 作者:殷天文  www.jianshu.com/p/0a485c965b8b 推荐阅**读(点击即可跳转阅读)** 1.  ****2. **** 3. 
    下一篇 
    Springboot配置详解 Springboot配置详解
    点击上方“后端技术精选”,选择“置顶公众号” 技术文章第一时间送达! 作者:SimpleWu cnblogs.com/SimpleWu/p/10032923.html 推荐阅**读(点击即可跳转阅读)** 1.  **2.