Java中短路运算符与逻辑运算符示例详解_java

来源:脚本之家  责任编辑:小易  

1、逻辑运算符(部分)

符号 名称
&& 短路与运算符
|| 短路或运算符
& 与运算符
| 或运算符

对于理工科学习者来说,逻辑运算是较为基础的概念,通常会在大一的离散数学课程中有所了解。在Java以及更多C-Like语言中,&和|会分别表示逻辑运算中的与、或,他们的运算结果与我们在数学书中所学的逻辑运算规则并无差异。但是,在实际编程的过程中,我们反而会更多使用&&和||,甚至不少同学都不了解&、|两个运算符。那么,这究竟是为什么呢?

2、短路运算符

让我们来回到最初学习逻辑运算时解决问题的真值表,以“或运算”为例:

a b 结果
true true true
true false true
false true true
false false false

a和b中,只要至少有一个为true,最终输出的结果则为true。那么,从算法优化的角度来思考问题的话,我们为了经过最少步骤还能输出可靠的结果,我们便可以把“或运算”定义为,有一个true,就输出true。

由此,“或运算”可以被优化为:从左向右,遇到有一个布尔表达式为true,则返回true,不进行之后的运算。

与之相似的,“与运算”可以被优化为:从左向右,遇到有一个布尔表达式为false,则返回false,不进行之后的运算。

故此,短路运算符被设计了出来。但为了兼顾“执行命令并返回”、“纯粹的数学计算”等多种应用场景,传统的非短路逻辑运算符也没有被短路逻辑运算符而取代。

此外,对于连写的短路运算符,如func1()||func2()||func3()||func4(),编译器也会为此优化,我们不妨来阅读这一部分的字节码来验证这个结论:

public static void main(String[] args) {
  boolean b1 = func1() || func2() || func3() || func4();
  System.out.println("------------------");
  boolean b2 = func1() | func2() | func3() | func4();
}

// func1() - func4() here

短路“或”的字节码如下:

0: invokestatic #7     // Method func1:()Z
3: ifne   24
6: invokestatic #13     // Method func2:()Z
9: ifne   24
12: invokestatic #16     // Method func3:()Z
15: ifne   24
18: invokestatic #19     // Method func4:()Z
21: ifeq   28
24: iconst_1
25: goto   29
28: iconst_0
29: istore_1

3行、9行、15行的ifne是将栈顶元素与0(false)相比,如果不为false则跳转到24行将常量1(true)入栈,完成赋值,会跳过其余的执行。直到最后21行,才将最后方法结果的值再与0相比,如果还是0,则将常量0入栈,完成赋值。

普通“或”等字节码如下:

38: invokestatic #7     // Method func1:()Z
41: invokestatic #13     // Method func2:()Z
44: ior
45: invokestatic #16     // Method func3:()Z
48: ior
49: invokestatic #19     // Method func4:()Z
52: ior
53: istore_2

则是普通的或运算,无跳转,顺序执行最后赋值。

3、应用与陷阱

在最起初,笔者重新认识短路运算符是在这样一段代码中:

public LoginCheckDTO XxxLoginCheck(String password) {
	//some codes
	if ( password == null || password.length() == 0 ) {
		return LoginCheckDTO.EMPTY_PASSWORD;
	}
	//some codes
}

当时笔者认为,如果password为null,在尝试调用password.length()时,会抛出空指针异常,故此写法不好。但在后来进行测试的时候,发现这样写并没有问题,查阅相关资料便了解了短路运算符的概念。

在这个例子中,当执行password == null返回true的时候,随后的表达式将不会被执行,就不存在抛出异常的情况了。这便是短路运算符较为常用的一个应用场景。

除此之外,我们还要警惕短路运算符导致的指令执行不完整。

譬如如下应用场景,我们希望利用条件语句来判断所有灯在上一状态是否都开着,并且无论如何我们希望最后打开所有的灯。但是我们错误使用了短路运算符:

public boolean checkAndTurnOnAll() {
	return checkAndTurnOn1() && checkAndTurnOn2();
}

private boolean checkAndTurnOn1() {
	boolean check = check1();
	turnOn1();
	return check;
}

private boolean checkAndTurnOn2() {
	boolean check = check2();
	turnOn2();
	return check;
}

在这个场景中,如果第一盏灯在上一个状态是关闭状态,在checkAndTurnOn1()中虽然会执行turnOn1(),并且返回false,但由于短路特性checkAndTurnOn2()并不会被执行,所以最后期望的看到所有的灯都被打开不一定会实现。这种情况应当使用&。

总结

到此这篇关于Java中短路运算符与逻辑运算符的文章就介绍到这了,更多相关Java短路运算符与逻辑运算符内容请搜索真格学网以前的文章或继续浏览下面的相关文章希望大家以后多多支持真格学网!

您可能感兴趣的文章:Java 逻辑运算符中&&与&,||与|的区别

  • 本文相关:
  • java执行cmd命令两种实现方法解析
  • java你告诉我 fail-fast 是什么鬼
  • java编程实现获取服务器ip地址及mac地址的方法
  • springboot集成springsecurity和jwt做登陆鉴权的实现
  • 基于java配置nginx获取真实ip代码实例
  • idea配置springboot热部署终极解决办法(解决热部署失效问题)
  • springboot框架打包体积简化过程图解
  • java实现较大二进制文件的读、写方法
  • java编程环境搭建和变量基本使用图文教程
  • mybatis中insert操作返回主键的实现方法
  • java 位运算符和逻辑运算符,有什么区别,&和&&
  • java 位运算符和逻辑运算符,有什么区别,&和&am...
  • JAVA中的逻辑运算符!
  • java中的逻辑运算符&&,||,!各个怎么用?举个比较...
  • java逻辑运算符作用
  • JAVA中,位运算符与布尔逻辑运算符的区别
  • java的运算符
  • JAVA逻辑运算符短路的疑问!!!!!求达人帮忙
  • JAVA中的位运算符怎么在逻辑运算符中也出现了。
  • java &和&&的区别,&是位运算符,&&是逻辑运算符,...
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全c#教程vbvb.netc 语言java编程delphijavaandroidiosswiftscala易语言汇编语言其它相关首页java 逻辑运算符中&&与&,||与|的区别java执行cmd命令两种实现方法解析java你告诉我 fail-fast 是什么鬼java编程实现获取服务器ip地址及mac地址的方法springboot集成springsecurity和jwt做登陆鉴权的实现基于java配置nginx获取真实ip代码实例idea配置springboot热部署终极解决办法(解决热部署失效问题)springboot框架打包体积简化过程图解java实现较大二进制文件的读、写方法java编程环境搭建和变量基本使用图文教程mybatis中insert操作返回主键的实现方法java使double保留两位小数的多方intellij idea 2020最新激活码(亲java8 十大新特性详解intellij idea 2020.2.3永久破解java.net.socketexception: connidea2020.2.2激活码与intellij ijava写入文件的几种方法分享java 十六进制与字符串的转换java环境变量的设置方法(图文教程2020.2 intellij idea激活与idea实例讲解java中动态代理和反射机制java更改图片大小示例分享springboot web项目打包实现过程解析一文读懂idea里面的artifact到底是什么java生产者消费者(线程同步)代码学习示例java实现的爬虫抓取图片并保存操作示例spring boot解决项目启动时初始化资源的方java验证电话号码的方法java多线程thread的实现方法代码详解springboot中使用aop打印接口日志的方法
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved