事故场景还原

最近在写一个项目的时候遇到一个这样一个问题,我简单的还原一下场景,这是模拟一个简单的管理系统

① 一张简单的客户表

CREATE TABLE customer(
id INT(11) NOT NULL AUTO_INCREMENT UNIQUE,
NAME VARCHAR(255) NOT NULL,
gender VARCHAR(255) NOT NULL,
phonenumber VARCHAR(255) NOT NULL,
balance DECIMAL(10,1) UNSIGNED,
PRIMARY KEY (id)
);

② CustomerService 层中的 updateBalance 方法

/**
* 通过id以及name字段查询用户信息
* @param id
* @param name
* @return
*/
public List<Custormer> queryByIdAndName(String id,String name) {
try {
return new CustormerDaoImpl().queryByIdAndName(id, name);
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}

③ 调用

public static void test() {
CustormerService cs = new CustormerService();
//用户输入的卡号和姓名,String类型,list在成员位置被定义
list = cs.queryByIdAndName(input_id,input_name()); if ( list != null) {
//获取充值或消费的金额数,这里简单用一个字符串模拟
String str = input_money;
BigDecimal bd = new BigDecimal(str);
updateBalance(input_id, bd, false);
}else {
OptionPane.showMessageDialog(null, "没有此用户信息");
}
} public static void updateBalance(String id, BigDecimal consumptionAmount, Boolean type) {
CustormerService cs = new CustormerService();
int back = cs.updateBalance(id, consumptionAmount, type);
if (back == 0) {
//我们用输出语句,模拟具体的弹窗或者显示的提示语
System.out.println("消费成功");
} else {
System.out.println("消费失败,请检查余额是否不足");
}
}

注意:省略了Dao层以及实体层等具体代码,同时对代码做了一定修改以及简化,旨在还原问题,如有纰漏请见谅

我们可以看到真正的消费扣款或者存款 是在这一句中被执行的 updateBalance(input_id, bd, false);,但是在执行对用余额的修改操作之前,我们需要对用户的身份进行核实,即通过 list = cs.queryByIdAndName(input_id,input_name()); 这一句进行校验,只有满足id和name在sql中查询,可以得到返回值则校验通过,进行下一步消费操作,所以我在test()方法中增添一个if判断 判断 list 的值是否为空

但是!每一次执行,无论卡号以及姓名输入是否正确,对金额的修改操作总会执行,这让我百思不得其解

问题所在

我们Service中的代码是这样的

try {
return new CustormerDaoImpl().queryByIdAndName(id, name);
} catch (SQLException e) {
e.printStackTrace();
return null;
}

查得到,返回一个用户信息集合,查不到则返回null

所以在list的判断中,我理所当然的使用了 if (list != null) 这样一个判断条件,而问题恰恰出现在这里

集合为空还是null?

集合为空:集合内没有元素,即为空

  • isEmpty:boolean isEmpty() : 如果此列表不包含元素,则返回 true

null:没有对 List 集合分配空间,即未实例化

你可以这样理解,逢时过节,锅里在煮饺子,你只有你的碗,在等饺子熟,所以此时你的碗中没有任何饺*,也就是集合为空的概念,但是如果你连碗都没拿,这个时候你就必须拿了碗,(分配了空间),饺子熟了你才有地方可以装饺子,但是你如果没有碗,就直接给你倒饺子,这个时候,就出现了空指针异常

总结:

  1. isEmpty() : 用于判断List中元素是否为空,必须在已经分配内存空间的前提下,否则报出异常

  2. == null : 用于判断 List 集合是否已经被分配内存空间

  3. list.size() == 0 : 与 isEmpty() 方法效果一致,但更推荐使用 isEmpty()

简单代码证明

  • 未实例化的情况
ArrayList<Student> list = null;
System.out.println(null == list);//返回 true
System.out.println(list.isEmpty());// 空指针异常
  • 实例化后的情况
ArrayList<Student> list = new ArrayList<Student>();
System.out.println(list.isEmpty());//返回 true
System.out.println(list == null);//返回 false

问题解决 以及搭配方式

由于我们将具体的 List实例化代码写在了DaoImpl层中的具体实现中 List<Custormer> custormer = new ArrayList<>();,所以执行校验方法后,实际上list已经被实例化了,所以如果使用 list != null来进行判断,这就会导致一直返回 true,所以我们将判断语句改为 if ( !list.isEmpty())就可以了

那么在我们实际开发中可以这样搭配,先判断是否已经分配空间,防止isEmpty判空时空指针异常,同时满足集合中没有元素

if(list!= null && !list.isEmpty()){
   //不为空执行的代码
}else{
   //为空执行的代码
}

还有一种做法就是在Service层中不返回null,而是返回一个空的集合 (已经实例化)

仁者见仁,智者见智,你觉得呢?

虽然这个问题很基础,但是确实让我头疼了好一阵,在开发的过程中,你遇到的一些莫名其妙的坑,往往来于自身对于基础知识的掌握没有很彻底,基础无论到什么时候,都是很重要啊!

结尾:

如果文章中有什么不足,或者错误的地方,欢迎大家留言分享想法,感谢朋友们的支持!

如果能帮到你的话,那就来关注我吧!如果您更喜欢微信文章的阅读方式,可以关注我的公众号

在这里的我们素不相识,却都在为了自己的梦而努力 ❤

一个坚持推送原创开发技术文章的公众号:理想二旬不止

判断List集合为空还是null的正确打开方式的更多相关文章

  1. Java之工具类:判断对象是否为空或null

    import java.lang.reflect.Array; import java.util.Collection; import java.util.Map; /** * 判断对象是否为空或nu ...

  2. c#判断字符串是否为空或null

    通常有: string str=""; .if(str=="") .if(str==String.Empty) .) 三种方法的效果一样,都可以判断字符串是否为 ...

  3. python判断字符串是否为空和null

    1.使用字符串长度判断 len(s==0)则字符串为空 test1 = '' if len(test1) == 0: print('test1为空串') else: print('test非空串,te ...

  4. Java循环删除集合多个元素的正确打开方式

    首先说下不正确的打开方式: 第一:使用for循环删除集合的元素,示例代码如下 ArrayList<String> list = new ArrayList<String>(Ar ...

  5. js中判断变量不为空或null

    var content=$("content").val(); if(!content){      alert("请输出内容!");      return; ...

  6. 判断List集合为空

    package org.springframework.util; CollectionUtils.isEmpty(list)

  7. 你可曾见过如此简单粗暴的JavaScript解说 -- if 判断的正确打开方式?

    在JavaScript中,对于 if else 的逻辑判断你肯定非常熟悉,本文罗列了几种你不一定知道的简写方式,仅供参考. 例子: 已知小明考了68分,小于60分为不及格,大于60分为及格,问:小明是 ...

  8. js 判断变量是否为空或未定义

    判断变量是否定义: if(typeof(hao) == "undefined"){ //未定义 }else{ //定义 } 判断变量是否为空或NULL,是则返回'', 反之返回原对 ...

  9. Velocity中判断表达式是不是为空

    Velocity中判断表达式是不是为空 $if ($null.isNull($mycoll) || $mycoll.size()==0) ${}与$!{}区别 例子: ${str}:如果str没有值, ...

随机推荐

  1. 《挑战30天C++入门极限》C++类对象的复制-拷贝构造函数

        C++类对象的复制-拷贝构造函数 在学习这一章内容前我们已经学习过了类的构造函数和析构函数的相关知识,对于普通类型的对象来说,他们之间的复制是很简单的,例如: int a = 10; int ...

  2. 《挑战30天C++入门极限》新手入门:C/C++中枚举类型(enum)

        新手入门:C/C++中枚举类型(enum) 如果一个变量你需要几种可能存在的值,那么就可以被定义成为枚举类型.之所以叫枚举就是说将变量或者叫对象可能存在的情况也可以说是可能的值一一例举出来. ...

  3. Java垃圾回收(java GC)

    一.GC的阶段 对每个对象而言,垃圾回收分为两个阶段:finalization和reclamation. finalization: 指运行这个对象的finalize的方法. reclamation: ...

  4. PHP如何解决网站大流量与高并发的问题(一)

    高并发的相关概念 在某个时间点,有多少个访问量 如果一个系统的日PV在千万以上,有可能是一个高并发的系统 QPS: 每秒钟请求或者查询的数量,在互联网领域,指每秒相应请求数(指HTTP请求) 吞吐量: ...

  5. java.lang.UnsupportedClassVersionError: com/mysql/cj/jdbc/Driver : Unsupported major.minor version 52.0 (unable to load class [com.mysql.cj.jdbc.Driver])

    原因: com/mysql/cj/jdbc/Driver是6.0版本的驱动,兼容JDK8环境,不兼容JDK7环境,在基于jdk7的tomcat中编译运行会出错,在基于jdk8的tomcat中编译运行则 ...

  6. MySQL两地三中心方案初步设计【转】

    整体内容会按照如下的方式来进行设计: 首先说下方案的背景,我参考了一些资料(参见附件). 方案背景 随着互联网业务快速发展,多IDC的业务支撑能力和要求也逐步提升,行业内的“两地三中心”方案较为流行. ...

  7. Dynamic Filter Networks

    Dynamic Filter Networks 2019-06-10 11:29:19 Paper:http://papers.nips.cc/paper/6578-dynamic-filter-ne ...

  8. jenkins持续集成springboot

    1.可以配置项目标签 PS:这里Default Value值修改为master 2.代码地址,这里并没有拉取制定标签的代码,而是拉取了最新版本代码,如果要拉取指定标签代码需要把*/master修改成$ ...

  9. YII2 输出 执行的 SQL 语句,直接用程序输出

    $query = User::find() ->,,,]) ->select(['username']) // 输出SQL语句 $commandQuery = clone $query; ...

  10. ISO/IEC 9899:2011 条款6.5.17——逗号操作符

    6.5.17 逗号操作符 语法 1.expression: assignment-expression expression    ,    assignment-expression 语义 2.一个 ...