- 你遇见过三木运算符的空指针吗?
NPE 异常是我们日常开发中最常见的一种异常情况,但在三目运算符中出现确实不是很常见,各位可以看下如下实例:
Java
public static void action1(){
boolean flag = true; // 设置成 true,保证条件表达式的表达式二一定可以执行
boolean simpleBoolean = false; // 定义一个基本数据类型的 boolean 变量
Boolean nullBoolean = null;// 定义一个包装类对象类型的 Boolean 变量,值为 null
boolean x = flag ? nullBoolean : simpleBoolean; // 使用三目运算符并给 x 变量赋值
}
大佬们觉得以上代码执行的结果会是什么?
没错,会抛出 NPE 异常。
这个问题还得回顾下三目运算符和自动拆装箱的概念,有兴趣了吧?系好安全带,发车了!
< 表达式 1> ? < 表达式 2> : < 表达式 3>
以上便是三目运算符的写法形式,通过 ?和 :组合的形式得到一个条件表达式。其中 ?运算符的含义是:先求表达式 1 的值,如果为真,则执行并返回表达式 2 的结果;如果表达式 1 的值为 假,则执行并返回表达式 3 的结果。
那自动拆装箱呢?还是直接代码说话吧。
Java
Integer i = 10; //自动装箱
int b = i; // 自动拆箱
自动装箱 : 就是将基本数据类型自动转换成对应的包装类。
自动拆箱:就是将包装类自动转换成对应的基本数据类型。
自动装箱都是通过包装类的 valueOf() 方法来实现的 . 自动拆箱都是通过包装类对象的 xxxValue() 来实现的(如 booleanValue()、longValue() 等)。
那回到问题,为什么三目运算符里会出现意想不到的 NPE 异常呢?
Java
boolean flag = true;
boolean simpleBoolean = false;
Boolean nullBoolean = null;
boolean x = flag ? nullBoolean.booleanValue() : simpleBoolean;
我们看下,三目运算符反编译后的代码就非常清楚为什么会出现 NPE 异常了,因为它反编译后将指向 null 值的 nullBoolean 自动拆箱导致的,我们总结下三目运算符的执行规律即可得到:
当第二位和第三位操作数的类型相同时,则三目运算符表达式的结果和这两位操作数的类型相同。当第二,第三位操作数分别为基本类型和该基本类型对应的包装类型时,那么该表达式的结果的类型要求是基本类型。
也就是说当:左右两项类型一个为包装类型一个为基本类型时,代码编译器会帮我们自动做一步拆箱操作。
你学会了吗?
- 你知道 ArrayList 的 subList 方法返回的是什么吗?
Returns a view of the portion of this list between the specifiedfro-mIndex, inclusive, and toIndex, exclusive.
这个是 JDK 源码中作者给我们的注释,也就是说 subList 返回的是一个视图,那什么是视图呢?
Java
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
这段是 subList的源码,看完源码你会发现 SubList 是在 ArrayList 里的一个内部类,这个类里面单独定义了 set/get/size/add/remove 等方法,也就是说它在执行 subList 时不会创建一个新的 List,而是直接引用了原有的 List 的视图,这也就意味着你对返回的视图或者原集合做的任何改动都会反应到这里,也就是说会出现隐秘性的 Bug。
你学会了吗?
- 为什么禁止使用 count(列名) 或 count(常量)来替代 count(*)?
关于 COUNT 函数,在 MySQL 官网中有详细介绍:
简单翻译一下:
1. COUNT(expr) ,返回 SELECT 语句检索的行中 expr 的值不为 NULL 的
数量。结果是一个 BIGINT 值。
2. 如果查询结果没有命中任何记录,则返回 0。
3. 但是,值得注意的是,COUNT(*) 的统计结果中,会包含值为 NULL 的行数。
那COUNT( 列名 )、COUNT( 常量 ) 和 COUNT(*) 之间的区别是什么呢?
COUNT( 常量 ) 和 COUNT(*) 表示的是直接查询符合条件的数据库表的行数。而 COUNT( 列名 ) 表示的是查询符合条件的列的值不为 NULL 的行数。
除 了 查 询 得 到 结 果 集 有 区 别 之 外,COUNT(*) 相 比 COUNT( 常 量 ) 和 COUNT( 列名 ) 来讲,COUNT(*) 是 SQL92 定义的标准统计行数的语法,因为他是标准语法,所以 MySQL 数据库对他进行过很多优化。
对于 COUNT(1) 和 COUNT(*),MySQL 的优化是完全一样的,根本不存在谁比谁快!
你学会了吗?