封面:学校内的秋天

背景:写这个的原因,也是我这两天凑巧看到的,虽然我一直有 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。
  2. 数据库的查询结果可能为 null。

  3. 集合里的元素即使 isNotEmpty,取出的数据元素也可能为 null。

  4. 远程调用返回对象时,一律要求进行空指针判断,防止 NPE。

  5. 对于 Session 中获取的数据,建议进行 NPE 检查,避免空指针。

  6. 级联调用 obj.getA().getB().getC() ;一连串调用,易产生 NPE。

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

五、自言自语

你好,我是博主宁在春主页

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

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

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

参考:Alibaba Java 开发手册

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

  1. 为什么阿里巴巴Java开发手册中强制要求整型包装类对象值用 equals 方法比较?

    在阅读<阿里巴巴Java开发手册>时,发现有一条关于整型包装类对象之间值比较的规约,具体内容如下: 这条建议非常值得大家关注, 而且该问题在 Java 面试中十分常见. 还需要思考以下几个 ...

  2. 为什么阿里巴巴Java开发手册中强制要求不要在foreach循环里进行元素的remove和add操作?

    在阅读<阿里巴巴Java开发手册>时,发现有一条关于在 foreach 循环里进行元素的 remove/add 操作的规约,具体内容如下: 错误演示 我们首先在 IDEA 中编写一个在 f ...

  3. 为什么阿里巴巴Java开发手册中强制要求接口返回值不允许使用枚举?

    在阅读<阿里巴巴Java开发手册>时,发现有一条关于二方库依赖中接口返回值不允许使用枚举类型的规约,具体内容如下: 在谈论为什么之前先来科普下什么是二方库,二方库也称作二方包,一般指公司内 ...

  4. 阿里巴巴开发手册强制使用SLF4J作为门面担当的秘密,我搞清楚了

    之前已经详细.全面地介绍了 Log4j,相信小伙伴们已经完全掌握了.那我在读嵩山版的阿里巴巴开发手册(没有的小伙伴,记着找我要)的时候,就发现了一条「强制」性质的日志规约: 应用中不可以直接使用日志系 ...

  5. 阿里巴巴Java开发手册中的DO、DTO、BO、AO、VO、POJO定义

    分层领域模型规约: DO( Data Object):与数据库表结构一一对应,通过DAO层向上传输数据源对象. DTO( Data Transfer Object):数据传输对象,Service或Ma ...

  6. 为什么阿里巴巴Java开发手册中不建议在循环体中使用+进行字符串拼接?

    之前在阅读<阿里巴巴Java开发手册>时,发现有一条是关于循环体中字符串拼接的建议,具体内容如下: 那么我们首先来用例子来看看在循环体中用 + 或者用 StringBuilder 进行字符 ...

  7. 为什么阿里巴巴Java开发手册中不允许魔法值出现在代码中?

    在阅读<阿里巴巴Java开发手册>时,发现有一条关于关于常量定义的规约,具体内容如下: 图中的反例是将数据缓存起来,并使用魔法值加链路 id 组成 key,这就可能会出现其他开发人员在复制 ...

  8. 阿里java开发手册中命名规约解读之DO/BO/DTO/VO/AO

    前言 在阅读<阿里巴巴Java开发手册>时,看到命名规则中有这样一条 虽然知道这些是根据Java对象的角色所分配名称的后缀,但是没有弄清楚分别是什么意思,日常开发中也没有使用到. 网上查找 ...

  9. Java开发笔记(二十八)布尔包装类型

    前面介绍了数值包装类型,因为不管是整数还是小数,它们的运算操作都是类似的,所以只要学会了Integer的用法,其它数值包装类型即可一并掌握.但是对于布尔类型boolean来说,该类型定义的是“true ...

随机推荐

  1. Python习题集(十)

    每天一习题,提升Python不是问题!!有更简洁的写法请评论告知我! https://www.cnblogs.com/poloyy/category/1676599.html 题目 使用列表生成式语法 ...

  2. Asp.Net 5上传文件 (Core API方式)

    参考文档 首先在控制器中注入IWebHostEnvironment IWebHostEnvironment提供有关正在运行应用程序的Web托管环境的信息. 属于命名空间Microsoft.AspNet ...

  3. Swagger-初见

    目录 Swagger简介 SpringBoot集成Swagger 配置Swagger 配置扫描接口 配置Swagger开关 配置API分组 实体配置 常用注解 Swagger简介 前后端分离 前端 - ...

  4. MAC地址知识

    1. 全球唯一无法保障. 软件工具可以修改网卡的MAC地址 2.不需要全球唯一. 只要保障局域网内不重复就行.    路由器 保证 数据在不同局域网内跳转.   如果局域网内使用集线器,那么可以设置相 ...

  5. Excel中怎么快速选中区域

    连续的表格选定 一张表格中会有不同的部分,若想选择某一个区域的数据的时候我们可以使用快捷键Ctrl+A,这是需要先选中第一个单元格,接着点击Ctrl+A即可选中连续的单元格.       汇总后需要汇 ...

  6. TP6出现错误 No input file specified.

    解决办法是打开public下的.htaccess文件, 把:RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L] 改为:RewriteRule ^(.*)$ index ...

  7. Shell系列(32)- 双分支if语句判断Apache服务是否启动

    #!/bin/bash #截取httped进程,并把结果赋予变量test test=$(ps -aux | grep "httpd" | grep -v "grep&qu ...

  8. Shell系列(9)- 用户自定义变量(2)

    定义变量 变量名=变量值 例如: x=123 mulu="当前目录下有 $(ls)" 备注: 变量名只能是字母.下划线.数字组成且不能以数字开头 变量等号两侧不能加空格 若变量值中 ...

  9. Appium和Selenium的区别和联系

    https://www.cnblogs.com/lv-lxz/p/11118862.html https://blog.csdn.net/weixin_42139375/article/details ...

  10. genymotion从本地拖拽apk到模拟器失败,报错“An error occured while deploying the file……”-解决方案

    前两篇已经讲过genymotion的安装了,但genymotion构建的安卓模拟器的界面比较简洁,什么软件都没.那么我们进行测试之前,先将需要测试的apk安装到模拟器中,一般来说,直接将apk文件从本 ...