不该被忽视的CoreJava细节(三)
一、不该被遗忘的移位位运算
本文主要介绍移位运算(Shift Operation), 适当介绍一下其它相关的位运算。
甭说计算机刚发明那会,就连21世纪初那段日子,计算机内存都是KB/MB计算的。编写的程序需要充分考虑计算机的储存容量,好的程序必须是执行效率高,代码精炼,占用资源尽可能少,不容许任何的浪费。可想而知,那个时候位运算带来的运行性能上的提升和内存资源消耗降低是多么重要。
现如今计算机行业高速发展,位运算带来的高效率等优势已经被整体硬件水平的质变所冲淡,但是为什么我们还要学习掌握位运算呢?答案就两个字:装逼。这就像图形界面已经这么发达了,为什么我还是会用shell一样,无非就是显摆
。
二、移位运算案例
1 /** 2 * Java移位运算: 3 * 1)带符号左移 << 4 * 2)带符号右移 >> 5 * 3)无符号右移 >>> 6 * 7 * 注意点: 8 * 1)本案例使用字面量10,默认为int型 9 * 2)Java移位运算不支持小数 10 */ 11 public class ShiftOperation { 12 public static void main(String[] args) { 13 // 正整数的带符号左移(0000_0000_0000_0000_0000_0000_0000_1010)B << 2 14 System.out.println(10 << 2); // 40 15 // 负整数的带符号左移 (1111_1111_1111_1111_1111_1111_1111_0110)B << 2 16 System.out.println(-10 << 2); // -40 17 18 // 正整数的带符号右移(0000_0000_0000_0000_0000_0000_0000_1010)B >> 2 19 System.out.println(10 >> 2); // 2 20 // 负整数的带符号右移 (1111_1111_1111_1111_1111_1111_1111_0110)B >> 2 21 System.out.println(-10 >> 2); //-3 22 23 // 正整数的带符号右移 (0000_0000_0000_0000_0000_0000_0000_1010)B >>> 2 24 System.out.println(10 >>> 2); // 2 25 // 负整数的带符号右移 (1111_1111_1111_1111_1111_1111_1111_0110)B >>> 2 26 System.out.println(-10 >>> 2); // 1073741821 27 } 28 }
这些运算有人做过规律总结,甚至还有公式,但是我个人不推荐,记住了又能怎么样呢。任何东西,只要能从本质上理解,这就说明你已经完全掌握了,公式只不过为了应付考试而已,没有任何实际意义。
三、移位运算原理简单探究(参考教材学习)
首先,问一个问题:为什么Java移位运算没有无符号左移运算符(<<<)?
但凡非生活琐事,常问为什么
对自身综合素质的提高大有裨益。这个问题近1年前我想过,今天也给大家分享一下。
1111_1111_1111_1111 << 2 结果:1111_1111_1111_1100 1111_1111_1111_1111 <<< 2 结果:1111_1111_1111_1100 结果完全相同,能少写一个<符号,何乐而不为呢 1111_1111_1111_1111 >> 2 结果:1111_1111_1111_111 负数带符号右移仍为负数 1111_1111_1111_1111 >>> 2 结果:0011_1111_1111_1111 负数无符号右移变成正数
说段题外话,十几天前,有同学晒了一张和众多书籍的合影,并说自己好像拥有好多知识。我回复了一条评论,有书籍并不代表有知识,有知识并不代表有文化,有文化并不代表有教养。其实,教育本身并不是等于教授知识,重要的是在于知识背后的思想。举些切合本节主题的例子,奥斯特发现电生磁,法拉第利用对称思想想到磁生电;麦克斯韦直到变电场可以产生变磁场,于是假设变磁场也可以激发变电场,于是有了电磁波的发现。
看到Java有>>>却没有<<<,这么奇怪,其实我们应该多去探究背后设计者是基于什么考虑的,或者你认为是基于什么考虑的。
移位运算的原理其实不难,真正略难的是从电路的角度来理解,在代码层次只要知道其运算规则即可。至少明确以下几点:
1)计算机中保存数据使用的是补码,正数的补码等于其原码、反码,负数的补码值上等于其反码加1。
2)原码和反码是非符号位按位取反。
3)正数符号位为0,负数符号位为1。
4)小数不能使用Java移位运算符进行运算。
5)带符号移位,左移右侧补0,右移左侧补符号位;无符号右移,左侧补0。
四、核心类库中移位运算案例
下面选择的是HashMap类中的一个方法。既有移位运算,又有异或运算,有兴趣的读者可以研究一下,今后会在集合框架专题中专门对HashMap类分析,尽请期待。
在Java源代码中大量用到了移位运算,比如二分搜索算法等等,应该引起注意。
五、简述Java中存在的位运算
Java位运算除了移位运算外,还有按位与(&)、按位或(|)、按位异或(^)、非(~)运算。能否运算符的有效使用,足够看出一个人的基本功。当然,如果要灵活运用这些操作符,需要对计算机底层有所了解,以及对操作符的运算性质了如指掌。
很多试题涉及到Java位运算符,今后都会以例题的形式展示给大家,然后慢慢的分析其中原理。