为什么阿里巴巴开发手册中强制要求 POJO 类使用包装类型?NPE问题防范

简介: 为什么阿里巴巴开发手册中强制要求 POJO 类使用包装类型?NPE问题防范


背景:写这个的原因,也是我这两天凑巧看到的,虽然我一直有 alibaba Java 开发手册,也看过不少次,但是一直没有注意过这个问题😂

属于那种看过,但又没完全看过👰

一起来看看吧冲咯🏂

hxdm,我写不出小故事😭,但是可不可以看在我写了不少,还算实用的份上,给个赞👍啊。

在这里请xdm 喝 🥤啦

一、前言🚕

今天在写一个AdvertVO类时,我当时用 id 是直接给了个 long,没有使用用包装类型,然后 idea 里面的 Alibaba Java Coding Guidelines 插件就直接给了个黄色波浪线,ALT+ENTER一看,阿里巴巴Java开发手册 的提示说:

关于基本数据类型与包装数据类型的使用标准如下:  1) 所有的POJO类属性必须使用包装数据类型。  2) RPC方法的返回值和参数必须使用包装数据类型。  3) 所有的局部变量推荐使用基本数据类型。

说明:POJO类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何NPE问题,或者入库检查,都由使用者来保证

我刚看的时候,稍稍有点点没完全理解这个意思(可能是我比较菜,没有经历过这样的场景),然后为了搞懂自己心里的小疑惑😂,就👇

接下来我们弄一个简单的例子来理解理解,之后再聊聊实际发生的场景,以及会产生的危害

二、例子🛵

public class Main {
    private static Integer a1;
    private static int a2;
    private static Boolean b1;
    private static boolean b2;
    public static void main(String[] args) {
        System.out.println("Integer ==> a1:"+a1);
        System.out.println("int     ==> a2:"+a2);
        System.out.println("Boolean ==> b1:"+b1);
        System.out.println("boolean ==> b2:"+b2);
    }
    /**
     * 结果:
     * Integer ==> a1:null
     * int     ==> a2:0
     * Boolean ==> b1:null
     * boolean ==> b2:false
     */
}

所有的包装类型在我们没有赋值的时候,都是直接默认 null 值的,而基本类型都会初始化一个默认值。

也就是说,包装类型的默认值都是null,而基本数据类型的默认值是一个固定值,如boolean是false,byte、short、int、long是0,float是0.0f等;

👨‍💻可能 xdm 平时有注意到,但又没有完全注意到,用 基本类型和包装类型之间的区别。下面我们用场景说一说区别:👩‍🏫

三、场景🛫

【正例】:数据库的查询结果可能是 null,因为自动拆箱,用基本数据类型接收有 NPE 风险。( NPE 下文有解释)

【反例】:某业务的交易报表上显示成交总额涨跌情况,即正负 x%,x 为基本数据类型,调用的 RPC 服务,调用不成功时,返回的是默认值,页面显示为 0%,这是不合理的,应该显示成中划线-。所以包装数据类型 的 null 值,能够表示额外的信息,如:远程调用失败,异常退出。

1)场景一⛵

我们再举一个扣费的例子,我们做一个扣费系统,扣费时需要从外部的定价系统中读取一个费率的值,我们预期该接口的返回值中会包含一个浮点型的费率字段。当我们取到这个值得时候就使用公式:金额*费率=费用 进行计算,计算结果进行划扣。

如果由于计费系统异常,他可能会返回个默认值,如果这个字段是 Double 类型的话,该默认值为 null ,如果该字段是 double 类型的话,该默认值为 0.0。

如果扣费系统对于该费率返回值没做特殊处理的话,拿到null值进行计算会直接报错,阻断程序。拿到 0.0可能就直接进行计算,得出接口为 0 后进行扣费了。这种异常情况就无法被感知。

有人说,那我可以对 0.0 做特殊判断,如果是 0 一样可以阻断报错啊。但是,这时候就会产生一个问题,如果允许费率是 0 的场景又怎么处理呢?(如下例)

一个小小结论:使用基本类型可能会在一定程度上增大系统的复杂性,让坑变得越来越多。 还有这种使用包装类型定义变量的方式,通过异常来阻断程序的运行,进而可以被立马识别到这种綫上问题。但是我们如果使用基本数据类型的话,系统可能认为无异常,从而继续运行。只能被动的测试出现问题,更甚的是如果是线上出现这种问题,我想可能...都明白哈。

2)场景二🌆

简单来说就是我们如果自定义了一个 Student 类,其中有一个属性是成绩 score .

如果用 Integer 而不用 int 定义,一次考试,学生可能没考,值是null,也可能考了,但考了0分,值是0.

public class Student  {
    private  Integer score;
    private  int score;
}

请注意这两个表达的状态明显不一样 。如果我们用包装类型的话,null的话证明没有考,0的话证明考了0分;但是如果我们用基本类型的话,这两种情况都是一个样的,没法区分的。

四、NPE 问题🗽

【推荐】防止 NPE,是程序员的基本修养,注意 NPE 产生的场景:

NPE,指为基本类型的数据返回null值,防止NPE是程序员的基本休养。所有NPE的场景:

  1. 返回类型为基本数据类型,return包装数据类型的对象时,自动拆箱有可能产生NPE。
public int f() {
      return Integer 对象;
 } 
如果为null,自动解箱抛NPE。
  1. 数据库的查询结果可能为 null。
  2. 集合里的元素即使 isNotEmpty,取出的数据元素也可能为 null。
  3. 远程调用返回对象时,一律要求进行空指针判断,防止 NPE。
  4. 对于 Session 中获取的数据,建议进行 NPE 检查,避免空指针。
  5. 级联调用 obj.getA().getB().getC() ;一连串调用,易产生 NPE。

正例:使用 JDK8 的 Optional 类来防止 NPE 问题。了解👉JDK8 Optional 类

五、自言自语🚏

希望本篇文章能让你感到有所收获!!!

我们:待别日相见时,都已有所成

欢迎大家一起讨论问题😁,躺了🛌

参考:Alibaba Java 开发手册

目录
相关文章
|
机器学习/深度学习 设计模式 算法
类型体系与基本数据类型(第三节)
类型体系与基本数据类型(第三节)
53 0
|
Java 程序员 API
Java8特性第三讲:如何使用Optional类优雅解决业务npe问题
Java8特性第三讲:如何使用Optional类优雅解决业务npe问题
|
11月前
|
Java 程序员
【零基础学Java】—异常体系(四十五)
【零基础学Java】—异常体系(四十五)
|
Java C语言
【java的类型数据】——八大类型数据(下)
【java的类型数据】——八大类型数据
47 0
|
Java
【java的类型数据】——八大类型数据(上)
【java的类型数据】——八大类型数据
58 0
|
Java
【Java】四大函数式接口
【Java】四大函数式接口
72 0
|
开发框架 安全 Java
Java高手速成 | Java集合类泛类型
Java高手是这样炼成的。
109 1
Java高手速成 | Java集合类泛类型
|
存储 缓存 Java
Java 的八大基本类型及其包装类型(超级详细)
Java 的八大基本类型及其包装类型(超级详细)
4597 0
|
缓存 Java
java八大包装类
java会事先创建好一个cache数组,用来缓存-128 - 127的数据,以提升访问效率👍 所以我们不难得出一个结论,当传入的数据范围在-128 to 127,则通过cache进行返回,否则将会new一个新的对象,故第二个输出为False 第三个输出:(x == y),通过以上,不难看出,输出为True
84 0
java八大包装类
Java八大常用类(三) String类(重要,重点掌握)
字符串相关类,面试问的多,但是应用简单 String类的简单掌握方法 package oop2.demo06; import javax.sound.midi.Soundbank; import java.util.Locale; import java.util.UUID; public class StringB { public static void main(String[] args) { String a = "beijing"; String b = ""; //空字符串 String c = null;