Java开发笔记(十五)短路逻辑运算的优势
前面提到逻辑运算只能操作布尔变量,这其实是不严谨的,因为经过Java编程实现,会发现“&”、“|”、“^”这几个逻辑符号竟然可以对数字进行运算。譬如下面的代码就直接对数字分别开展了“与”、“或”、“异或”运算:
// 3的二进制为00000011,7的二进制为00000111
int andNumber = 3&7; // 对两个数字进行“按位与”运算
System.out.println("andNumber="+andNumber);
int orNumber = 3|7; // 对两个数字进行“按位或”运算
System.out.println("orNumber="+orNumber);
int xorNumber = 3^7; // 对两个数字进行“按位异或”运算
System.out.println("xorNumber="+xorNumber);
上述代码也能成功编译运行,运行结果如下所示:
andNumber=3
orNumber=7
xorNumber=4
究其原因,这三个逻辑符号原是按位逻辑运算。所谓按位逻辑,指的是先将操作数转成二进制,再对二进制的操作数逐位进行逻辑运算,最后把每位的逻辑结果重新拼成一个二进制的运算值。例如数字3的二进制表达为00000011,数字7的二进制表达为00000111,那么对这两个二进制数进行“按位与”运算,得到的二进制结果为00000011即数字3;同样对这两个二进制数进行“按位或”运算,得到的二进制结果为00000111即数字7;继续对这两个二进制数进行“按位异或”运算,得到的二进制结果为00000100即数字4。
以上的实验结果,说明了逻辑与、或、异或符号实质是按位逻辑运算,之前的布尔变量只是按位逻辑的一种运算类型。既然按位逻辑比较的是左右两边的各个二进制位,就意味着必须先确定左右两边的操作数值,然后才能对两个操作数进行按位运算。这么看来,按位逻辑并非真正意义上的逻辑操作,正常情况的逻辑运算应当具备下列特征:
1、只判断真和假,不判断0和1,更不是什么逐位判断;
2、对于“与”运算,一旦左边的操作数为假,则不管右边为何,运算结果一定为假;
3、对于“或”运算,一旦左边的操作数为真,则不管右边为何,运算结果一定为真;
对比发现,按位逻辑不但不符合上述的第一点特征,也不符合第二点和第三点特征,因为按位逻辑需要左右两边都确定之后,才能墨守成规进行逻辑运算。显然这样做并不经济,倘若左边操作数就能确定运算结果,那又何苦画蛇添足进行右边的冗余计算?为解决按位逻辑存在的问题,Java引入了新的短路符号来帮忙,包括短路与符号“&&”和短路或符号“||”,短路的意思是:如果左边已经接通,那就不绕道右边了。
话虽如此,但又如何证明短路逻辑是否真的高效呢?下面通过一个例子来分辨按位逻辑和短路逻辑之间的区别,关键在于逻辑符号的右边需要修改变量值,为此引入了自增符号“++”。具体的逻辑运算代码如下所示,主要是比较逻辑与“&”和短路与“&&”的运算结果:
int i=1, j=1;
// 对于按位逻辑运算,需要等待左右两边都计算完毕,然后进行按位逻辑判断
boolean result1 = 3>4 & ++i<5;
System.out.println("result1="+result1);
System.out.println("i="+i);
// 对于短路逻辑运算,一旦左边的计算能够确定结果,就立即返回逻辑判断的值,此时不再进行右边的计算
boolean result2 = 3>4 && ++j<5;
System.out.println("result2="+result2);
System.out.println("j="+j);
运行以上示例代码,得到下述的运算日志:
result1=false
i=2
result2=false
j=1
可见两个逻辑式子的运算结果都为false,不同之处在于:“&”符号同时进行了左右两边的运算,所以i++执行之后i值变为2;而“&&”符号先进行左边运算,发现3>4为假,说明与运算肯定为假,此时整个式子直接返回假,不再执行右边的计算,于是j值仍然为1(j++未执行)。从该实验看到,短路逻辑运算名副其实,其效率高于按位逻辑运算,因而在实际开发过程中,更经常使用短路符号“&&”和“||”进行逻辑运算,很少使用单个的“&”和“|”。
Java开发笔记(十五)短路逻辑运算的优势的更多相关文章
- Java开发笔记(五十)几种开放性修饰符
前面介绍子类继承父类的时候,提到了public(公共)和private(私有)两个修饰符,其中public表示它所修饰的实体是允许外部访问的:而private表示它所修饰的实体不允许外部访问,只能在当 ...
- Java开发笔记(五十二)对象的类型检查
前面介绍了类的多态性,来自于鸡类的实例chicken,既能用来表达公鸡实例,也能用来表达母鸡实例.可是这导致了一个问题,假如在call方法内部需要手工判断输入参数属于公鸡实例还是母鸡实例,那该如何是好 ...
- Java开发笔记(五十四)内部类和嵌套类
通常情况下,一个Java代码文件只定义一个类,即使两个类是父类与子类的关系,也要把它们拆成两个代码文件分别定义.可是有些事物相互之间密切联系,又不同于父子类的继承关系,比如一棵树会开很多花朵,这些花儿 ...
- Java开发笔记(五十五)关键字static的用法
前面介绍嵌套类的时候讲到了关键字static,用static修饰类,该类就变成了嵌套类.从嵌套类的用法可知,其它地方访问嵌套类之时,无需动态创建外层类的实例,直接创建嵌套类的实例就行.其实static ...
- Java开发笔记(五十六)利用枚举类型实现高级常量
前面介绍了联合利用final和static可实现常量的定义,该方式用于简单的常量倒还凑合,要是用于复杂的.安全性高的常量,那就力不从心了.例如以下几种情况,final结合static的方式便缺乏应对之 ...
- Java开发笔记(五十八)简单接口及其实现
前面介绍了抽象方法及抽象类的用法,看似解决了不确定行为的方法定义,既然叫唤动作允许声明为抽象方法,那么飞翔.游泳也能声明为抽象方法,并且鸡类涵盖的物种不够多,最好把这些行为动作扩展到鸟类这个群体,于是 ...
- Java开发笔记(五十九)Java8之后的扩展接口
前面介绍了接口的基本用法,有心的朋友可能注意到这么一句话“在Java8以前,接口内部的所有方法都必须是抽象方法”,如此说来,在Java8之后,接口的内部方法也可能不是抽象方法了吗?之所以Java8对接 ...
- Java开发笔记(五十一)多态的发生场景
江湖上传闻,面向对象之所以厉害,是因为它拥有封装.继承与多态三项神技,只要三板斧一出,号令天下谁敢不从.前面费了老大的劲才讲清楚封装和继承,那么多态又是怎样的神乎其神呢?下面先通过一个简单的例子来说明 ...
- Java开发笔记(五十三)关键字final的用法
前面介绍了多态的相关用法,可以看到一个子类从父类继承之后,便能假借父类的名义到处晃悠.这种机制在正常情况之下没啥问题,但有时为了预防意外发生,往往只接受当事人来处理,不希望它的儿子乃至孙子来瞎掺和.可 ...
- Java开发笔记(五十七)因抽象方法而产生的抽象类
前面介绍了类的常见用法,令人感叹面向对象的强大,几乎日常生活中的所有事物,都可以抽象成Java的基类及其子类.然而抽象操作也有副作用,就是某个抽象而来的行为可能是不确定的,比如半夜鸡叫,如果是公鸡则必 ...
随机推荐
- [转载]SSH框架搭建详细图文教程
http://www.cnblogs.com/hoobey/p/5512924.html
- HBuilder git合作-上传项目到Git Hub
1.初始项目的创建 这里假设你已经在Git Hub上面建立好了代码的远程仓库,并已经邀请好了队员 在HBuidler中创建好初始的项目,然后右键,"Team"->" ...
- SQL Server Service Broker创建单个数据库会话(消息队列)
概述 SQL Server Service Broker 用来创建用于交换消息的会话.消息在目标和发起方这两个端点之间进行交换.消息用于传输数据和触发消息收到时的处理过程.目标和发起方既可以在同一数据 ...
- Trie 简介
一.Trie简介 在计算机科学中,Trie,又称字典树.前缀树.单词查找树或键树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎 ...
- SVN和Git的功能和区别,尚学堂SVN和Git学习视频资料免费下载
对于软件开发人员来说,版本控制系统再熟悉不过了,所谓版本控制系统就是软件项目开发过程中用于储存开发人员所写代码所有修订版本的软件.目前常见的版本控制系统分为集中式版本控制系统(SVN)和分布式版本控制 ...
- [Swift]LeetCode145. 二叉树的后序遍历 | Binary Tree Postorder Traversal
Given a binary tree, return the postorder traversal of its nodes' values. Example: Input: [1,null,2, ...
- Python内置函数(21)——filter
英文文档: filter(function, iterable) Construct an iterator from those elements of iterable for which fun ...
- qt系统托盘显示、无主窗体
系统图盘是应用程序经常用到的一个控件,当应用程序需要长时间存在的时候,这个控件会变得非常有用,比如,窗口隐藏,显示,关于.关闭等接口都可以放在图盘中处理,今天与到一个问题,需求是这样的:只需要显示图盘 ...
- .net core使用RPC方式进行高效的HTTP服务访问
传统的HTTP接口调用是一件比较繁琐的事情,特别是在Post数据的时候:不仅要拼访问的URL还是把数据序列化成流的方式给Request进行提交,获取Respons后还要对流进行解码.在实际应用虽然可以 ...
- .net core通过多路复用实现单服务百万级别RPS吞吐
多路复用其实并不是什么新技术,它的作用是在一个通讯连接的基础上可以同时进行多个请求响应处理.对于网络通讯来其实不存在这一说法,因为网络层面只负责数据传输:由于上层应用协议的制订问题,导致了很多传统服务 ...