这次面试被逻辑运算符给“算计”了,读者:我想哭~
The following article is from 鸭哥聊Java Author 鸭哥
因此,他才鼓足勇气,决定拼死一战。然而,一面中,却被逻辑运算符给“算计”了~
到底是怎么样的一到题呢?让我慢慢来给他和在坐的小伙伴分析一下。
说实话,这是一份笔试题中的一道选择题,他当时选错了,记忆犹新。后来,他跟这个面试官互加了微信,了解了一下,他们公司专门有一个面试题库,会随机从题库里面,取几道题来,来考查应聘者的基础知识。
好了,切入正题。
# 面试题
先来看面试题,如下:
public class Test{
public static void main(String[] args){
int x = 0;
int y = 0;
int k = 0;
for (int z = 0; z < 5; z++) {
if ((++x > 2) && (++y > 2) && (k++ > 2))
{
x++;
++y;
k++;
}
}
System.out.println(x + "" + y + "" + k);
}
}
上面程序的输出结果为:
A. 432 B. 531 C. 421 D. 523
来来来,先选择你心目中的答案,后面揭晓。
# 考查知识点
首先,我们应该明确题目涉及的知识点,显然,上面的题目考察的是逻辑运算符的知识。
提到逻辑运算符,我们首先想到的是 `&&` 和 `||` ,即逻辑与和逻辑或,同时不要忘了 逻辑非 `!` 。这三个逻辑运算符,逻辑与和逻辑或是二元运算符(所谓的二元运算,是指对两个操作数进行运算),而逻辑非则是一元运算符。
关于 `&&` 和 `||` ,一个常见的疑问或者考点就是,一个表达式是否是短路(short-circuits)的。如果由左端表达式可推算出整个表达式的值,我们称为“短路”,始终执行逻辑运算符两边的表达式称为“非短路”。逻辑与和逻辑或构成的表达式是否具有短路特性呢?我们可以用实例验证。
//需要验证的内容如下:
if(a && b) //如果 a 为 false, Java还会校验 b 吗?
if(a || b) //如果 a 为 true, Java还会校验 b 吗?
鸭哥应该给大家讲清楚了吧!
# 实践出真知
受文章开头题目的设计思路启发,我们可以用下面的例子验证逻辑与和逻辑或运算符的特性:
public class FunnyTest{
public static void main(String[] args){
int a = 0;
int b = 0;
if((a++ > 0) && (b++ > 0)) ;
System.out.println("如果结果为1 0,则逻辑与具有短路特性:" + a +" " + b);
//此时a = 1, b = 0
if((a++ > 0) || (b++ > 0)) ;
System.out.println("如果结果为2 0,则逻辑或具有短路特性:" + a +" " + b);
}
}
程序的运行结果为:
分析:
a, b 的初始值均为 0,
第一个 if 条件执行后, a 的值加 1 ,b 的值不变,说明当 Java 执行 `a++ > 0` 的结果为 `false` 后,整个表达式即为 `false`,不再验证 `b++ > 0` 的值;
第二个 if 条件也是同样的道理,a = 1, `a++ > 0` 为 `true` ,整个表达式为 `true` ,不再验证 `b++ > 0` 的值。
所以,`&&` 和 `||`组成的表达式都具有短路特性
# 回归题目
回到文章开头的题目,模拟程序的执行过程如下:
当z=0,执行++x > 2不成立, &&后面不执行,此时 x=1,y=0,k=0;
当z=1,执行++x > 2不成立, &&后面不执行,此时 x=2,y=0,k=0;
当z=2, 执行++x > 2成立, 继续执行 ++y > 2不成立 , &&后面不执行, 此时 x=3,y=1,k=0;
当z=3,执行++x > 2成立,继续执行++y > 2不成立 , &&后面不执行, 此时 x=4,y=2,k=0;
当z=4,执行++x > 2成立,继续执行 ++y > 2成立 , 继续执行k++>2 ,不成立,此时 x=5,y=3,k=1;
(注意:5次循环都没有满足if条件)
当z=5,不满足条件for循环条件,跳出循环。
打印结果:x=5, y = 3, k = 1。所以,正确答案为 B ,你答对了吗?
# 引申思考
我们平时工作,很多场景其实都利用了 `&&` 和 `||` 运算符的短路特性,比如字符串的判断及后续处理:
我们可以这样写:
if (str != null && !str.isEmpty()) {
doSomethingWith(str);
}
也可以这么写:
if (str == null || str.isEmpty()) {
unusableString();
} else {
doSomethingWith(str);
}
如果没有短路特性,上述写法是会报异常的。因为若str = null ,执行 str.isEmpty() 时将会报NullPointerException。也就是说,上述两种写法,&& 和 || 左右两侧表达式的顺序不能互换,必须先判断 str 是否为 null , 再执行str.isEmpty().。
这个知识点,你get到了吗?你工作中,因为逻辑运算符踩过什么坑?欢迎在评论区与大家分享!
哇!IntelliJ IDEA 2021.1 中竟然有这么多牛逼的插件~ 在项目中用了Arrays.asList、ArrayList的subList,被老大公开批评~ 国内某 "大型直播平台" 彻底凉了,因为搞“色情”~