版权声明:本文为博主原创文章。未经博主同意不得转载。 https://blog.csdn.net/zjx409/article/details/37569055

左移运算符(<<)

基本使用方法

将一个运算对象的各二进制位所有左移若干位(左边的二进制位丢弃,右边补0)。

例:a = a << 2 将a的二进制位左移2位,右补0,

左移1位后a = a *2; 

若左移时舍弃的高位不包括1,则每左移一位。相当于该数乘以2。

举例以及困惑

给出以下的程序,大家能够猜一猜结果是什么?
public class MainClass {
public static void main(String[] args) {
long i = 1L << 3;
System.out.println(Long.toBinaryString(i));
i = 1L << 63;
System.out.println(Long.toBinaryString(i));
i = 1L << 64;
System.out.println(Long.toBinaryString(i)); }
}

以下是输出的结果:

1000<pre name="code" class="java">100000000000000000000000000000000000000000000000000000000000000

1


是不是跟想象的不同?上面明明说过左边的二进制位丢弃。如今左移64位不应该是0吗?怎么会出现1呢?难道是循环移位吗?

详解

首先举一个样例来说明不是循环移位:
假设上面的程序改为
i = 3L << 63

程序的结果仍然为

1000000000000000000000000000000000000000000000000000000000000000
那么就说明Java中的移位运算不是循环的。

那对上面的问题又怎么解释呢?
在JLS(Java Language Specific 15.19)中有例如以下解释:
If the promoted type of the left-hand operand is int, only the five lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator & (§15.22.1) with the mask value 0x1f (0b11111). The shift distance actually used is therefore always in the range 0 to 31, inclusive.

If the promoted type of the left-hand operand is long, then only the six lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator & (§15.22.1) with the mask value 0x3f (0b111111). The shift distance actually used is therefore always in the range 0 to 63, inclusive.

意思是说:在移位运算中,假设被移位的操作数是int类型的,那么仅仅会用到移位数的最低5位,假设是long类型的,那么仅仅会用到低六位。
那么为什么是低5位和低6位呢?相信你应该明确了,int共占32位,long占64位,正好是2的5次幂和6次幂。能够理解为分别对32 和 64 取模。所以1L << 64 就会变成 1L << 0。结果自然就是1了。
关于网上的说法:
网上有很多资料说上述定义是由编译器完毕的,即假设写 1L << 64 。则编译器会将文件编译为  1L << 0 。可是经过本人的实验发现这个过程会发生在执行时而不是编译位class文件的过程。以下是个人所做的一些实验。
实验过程:
  1. 将程序编译为class文件
  2. 使用javap输出class文件的内容
  3. 使用HSDIS输出虚拟机执行的汇编代码
源程序:
public class SF{
public static void main(String[] args) {
new SF().sh(1,2);
} public int sh(int a , int b){
return (a << 32);
}
}

注意此处使用的是int类型

在windows环境下的批处理文件
javac SF.java
javap -verbose SF > sfp.txt
java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -Xcomp -XX:CompileCommand=dontinline,*SF.sh -XX:CompileCommand=compileonly,*SF.sh SF > sfasm.txt
pause

这里须要用到HSDIS插件才干输出汇编代码。

能够到https://kenai.com/projects/base-hsdis/downloads下载,可是上面并不提供windows版本号的插件,能够到http://hllvm.group.iteye.com/下载windows
X86的插件。

以下是javap的结果。
iload_1 为取得參数a,在栈中push  32  后,进行移位操作。ishl中的i指代的是int的移位操作。
再看反汇编的输出:
[Verified Entry Point]
0x01c92e50: mov %eax,-0x4000(%esp)
0x01c92e57: push %ebp
0x01c92e58: sub $0x18,%esp ;*iload_1
; - SF::sh@0 (line 7) 0x01c92e5b: shl $0x0,%edx
0x01c92e5e: mov %edx,%eax
0x01c92e60: add $0x18,%esp
0x01c92e63: pop %ebp
0x01c92e64: test %eax,0x140100 ; {poll_return}

看到在分配完栈空间后,在0x01c92e5b这一行中,进行了移位。操作数为0x0

Java移位运算符 “的更多相关文章

  1. java移位运算符具体解释

    java移位运算符不外乎就这三种:<<(左移).>>(带符号右移)和>>>(无符号右移). 1. 左移运算符 左移运算符<<使指定值的全部位都左移 ...

  2. java移位运算符详解

    http://soft.chinabyte.com/database/195/11553695.shtml java移位运算符不外乎就这三种:<<(左移).>>(带符号右移)和 ...

  3. java 移位运算符

    java中有三种移位运算符 <<      :     左移运算符,num << 1,相当于num乘以2 >>      :     右移运算符,num >& ...

  4. Java移位运算符详解实例

    移位运算符它主要包括:左移位运算符(<<).右移位运算符(>>>).带符号的右移位运算符(>>),移位运算符操作的对象就是二进制的位,可以单独用移位运算符来处 ...

  5. Java移位运算符详解实例——左移位运算符>>、带符号的右移位运算符>>

    移位运算符也针对二进制的“位”,它主要包括:左移位运算符(<<).右移位运算符(>>>).带符号的右移位运算符(>>). 1.左移运算符左移运算符用“< ...

  6. java移位运算符:<<(左移)、>>(带符号右移)和>>>(无符号右移)。

    1. 左移运算符 左移运算符<<使指定值的所有位都左移规定的次数. 1)它的通用格式如下所示: value << num num 指定要移位值value 移动的位数. 左移的规 ...

  7. 使用java移位运算符进行转化

    import java.util.Scanner; public class Main { public static void main(String[] args) { new Main().sy ...

  8. 计算机原码、补码、反码与java移位运算符(<</>>/>>>)

    一.机器值和真值 1.机器值 一个数在计算机中的二进制表示形式,  叫做这个数的机器数.机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1. 比如,十进制中的数 +3 ,计算机 ...

  9. java移位运算符

    http://www.iteye.com/topic/766461 这篇博客讲的很清楚

随机推荐

  1. bzoj1627 / P2873 [USACO07DEC]泥水坑Mud Puddles

    P2873 [USACO07DEC]泥水坑Mud Puddles bfs入门. 对于坐标为负的情况,我们可以给数组下标加上$abs(min(minx,miny))$转正(根据题意判断) #includ ...

  2. hdu 1498 50 years, 50 colors 最小点覆盖

    50 years, 50 colors Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  3. hihocode 股票价格 优先队列+map

    股票价格 时间限制:20000ms 单点时限:2000ms 内存限制:256MB 描述 小Hi最近在分析一支股票的价格走势,他需要一个程序来辅助分析.这个程序会接收3种消息(指令): 价格信息,格式是 ...

  4. [java]java String.split()函数的用法分析

    转自:http://swiftlet.net/archives/709 一.在java.lang包中有String.split()方法的原型是: public String[] split(Strin ...

  5. Python yield 用法

    一.环境 python 3.6 二.yield 说明 yield 是一个生成器,可以用于迭代.也是一个类似 return 的关键字,迭代一次遇到yield时就返回yield后面(右边)的值. 重点是: ...

  6. PrestaShop 1.7 用户付款的时候无法支付错误

    用户付款的时候出现错误,错误的信息是没有支付方式. 这个有可能是你后台支付的国家限制没有选择. 请确定你已经选择了支付国家限制已经选择了. 当选择成功后,你应该可以看到下面的选择项.

  7. Appium 自动化测试(9) -- 在Uiautomator中查看webview元素

    在uiautomator中,直接查看不到webview中的元素,不知道大家遇到过没有?如下 解决方法如下: step0:将uiautomator关闭 step1:在appium 中,设置Android ...

  8. HDU - 4804 Campus Design 轮廓线dp

    题意:一个nm的矩阵被12的骨牌和11的骨牌完全覆盖,11的骨牌只能放c-d次,矩阵中有障碍物 题解:dp[i][j][k]表示到了第i行,第j个状态,放过k个11的骨牌,当前位有障碍物时只有一种转移 ...

  9. run jdeveloper, unable to create an instance of the Java Virtual Machine Located at path:

    刚才打开 jdevW.exe 时提示如下错误: Unable to create an instance of the Java Virtual MachineLocated at path:x:\x ...

  10. OC 数据持久化(数据本地化)- 本地存储

    // // ViewController.m // IOS_0113_本地存储 // // Created by ma c on 16/1/13. // Copyright (c) 2016年 博文科 ...