前面提到逻辑运算只能操作布尔变量,这其实是不严谨的,因为经过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开发笔记(十五)短路逻辑运算的优势的更多相关文章

  1. Java开发笔记(五十)几种开放性修饰符

    前面介绍子类继承父类的时候,提到了public(公共)和private(私有)两个修饰符,其中public表示它所修饰的实体是允许外部访问的:而private表示它所修饰的实体不允许外部访问,只能在当 ...

  2. Java开发笔记(五十二)对象的类型检查

    前面介绍了类的多态性,来自于鸡类的实例chicken,既能用来表达公鸡实例,也能用来表达母鸡实例.可是这导致了一个问题,假如在call方法内部需要手工判断输入参数属于公鸡实例还是母鸡实例,那该如何是好 ...

  3. Java开发笔记(五十四)内部类和嵌套类

    通常情况下,一个Java代码文件只定义一个类,即使两个类是父类与子类的关系,也要把它们拆成两个代码文件分别定义.可是有些事物相互之间密切联系,又不同于父子类的继承关系,比如一棵树会开很多花朵,这些花儿 ...

  4. Java开发笔记(五十五)关键字static的用法

    前面介绍嵌套类的时候讲到了关键字static,用static修饰类,该类就变成了嵌套类.从嵌套类的用法可知,其它地方访问嵌套类之时,无需动态创建外层类的实例,直接创建嵌套类的实例就行.其实static ...

  5. Java开发笔记(五十六)利用枚举类型实现高级常量

    前面介绍了联合利用final和static可实现常量的定义,该方式用于简单的常量倒还凑合,要是用于复杂的.安全性高的常量,那就力不从心了.例如以下几种情况,final结合static的方式便缺乏应对之 ...

  6. Java开发笔记(五十八)简单接口及其实现

    前面介绍了抽象方法及抽象类的用法,看似解决了不确定行为的方法定义,既然叫唤动作允许声明为抽象方法,那么飞翔.游泳也能声明为抽象方法,并且鸡类涵盖的物种不够多,最好把这些行为动作扩展到鸟类这个群体,于是 ...

  7. Java开发笔记(五十九)Java8之后的扩展接口

    前面介绍了接口的基本用法,有心的朋友可能注意到这么一句话“在Java8以前,接口内部的所有方法都必须是抽象方法”,如此说来,在Java8之后,接口的内部方法也可能不是抽象方法了吗?之所以Java8对接 ...

  8. Java开发笔记(五十一)多态的发生场景

    江湖上传闻,面向对象之所以厉害,是因为它拥有封装.继承与多态三项神技,只要三板斧一出,号令天下谁敢不从.前面费了老大的劲才讲清楚封装和继承,那么多态又是怎样的神乎其神呢?下面先通过一个简单的例子来说明 ...

  9. Java开发笔记(五十三)关键字final的用法

    前面介绍了多态的相关用法,可以看到一个子类从父类继承之后,便能假借父类的名义到处晃悠.这种机制在正常情况之下没啥问题,但有时为了预防意外发生,往往只接受当事人来处理,不希望它的儿子乃至孙子来瞎掺和.可 ...

  10. Java开发笔记(五十七)因抽象方法而产生的抽象类

    前面介绍了类的常见用法,令人感叹面向对象的强大,几乎日常生活中的所有事物,都可以抽象成Java的基类及其子类.然而抽象操作也有副作用,就是某个抽象而来的行为可能是不确定的,比如半夜鸡叫,如果是公鸡则必 ...

随机推荐

  1. 梯度提升决策树(GBDT)

    1.提升树 以决策树为基函数的提升方法称为提升树.决策树可以分为分类树和回归树.提升树模型可以表示为决策树的加法模型. 针对不同的问题的提升术算法的主要区别就是损失函数的不同,对于回归问题我们选用平方 ...

  2. 【阿里聚安全·安全周刊】女主换脸人工合成小电影|伊朗间谍APP苹果安卓皆中招

    本周的七个关键词: 人工智能 丨 HTTP链接=不安全链接 丨  滑动验证码 丨 伊朗间谍APP 丨 加密挖矿 丨  Android应用测试速查表 丨 黑客销售签名证书 -1-   [人工智能]女主换 ...

  3. jenkins:一键回滚站点集群

    最近在学习jenkins过程中整理了大量资料,都收录在<jenkins自动化工具使用教程>,但依然缺少一些具体实现细节. 这篇文章,介绍jenkins做集群回滚时的两个设计方案,让一键回滚 ...

  4. 发一些Java面试题,上海尚学堂Java学员面试遇到的真题,值得学习

    1. 下面哪些是Thread类的方法() A start()       B run()       C exit()       D getPriority() 答案:ABD 解析:看Java AP ...

  5. PCD文件格式详解及在PCL下读取PCD文件

    一.PCD简介 1.1 PCD版本 在点云库PCL 1.0发布之前,PCD文件格式就已经发展更新了许多版本.这些新旧不同的版本用PCD_Vx来编号(例如PCD_V5.PCD_V6和PCD_V7等),分 ...

  6. ALL_SOURCE

    类型:View Owner: SYS 内容: 记录了该用户可访问的所有数据库对象的脚本信息(DDL) 字段:  OWNER: 对象的Owner NAME: 对象名称 TYPE: 对象类型,如FUNCT ...

  7. ThinkPHP 数据库操作(二) : 增删改查

    基本使用 可以直接使用数据库运行原生SQL操作了,支持 query (查询操作)和 execute (写入操作)方法,并且支持参数绑定. Db::query('select * from think_ ...

  8. IntelliJ IDEA 自定义方法注解模板

    最近没啥事开始正式用Eclipse 转入 idea工具阵营,毕竟有70%的开发者在使用idea开发,所以它的魅力可想而知.刚上手大概有一天,就知道它为啥取名为 intelli(智能化)了,确实很智能, ...

  9. 【Spark篇】---SparkStreaming算子操作transform和updateStateByKey

    一.前述 今天分享一篇SparkStreaming常用的算子transform和updateStateByKey. 可以通过transform算子,对Dstream做RDD到RDD的任意操作.其实就是 ...

  10. SpringCloud(1)---基于RestTemplate微服务项目案例

    基于RestTemplate微服务项目 在写SpringCloud搭建微服务之前,我想先搭建一个不通过springcloud只通过SpringBoot和Mybatis进行模块之间额通讯.然后在此基础上 ...