版权声明:本文为博主原创文章。未经博主同意不得转载。 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. Entity Framework在WCF中序列化的问题(转)

    问题描述 如果你在WCF中用Entity Framework来获取数据并返回实体对象,那么对下面的错误一定不陌生. 接收对 http://localhost:5115/ReService.svc 的 ...

  2. PYPI 国内源

    搬砖自http://www.cnblogs.com/sunnydou/p/5801760.html 阿里云 http://mirrors.aliyun.com/pypi/simple/ 中国科技大学  ...

  3. import static

    import static(静态导入)是JDK1.5中的新特性,一般我们导入一个类都用 import com.....ClassName;而静态导入是这样:import static com..... ...

  4. SQL学习笔记一之初识数据库

    阅读目录 一 数据库管理软件的由来 二 数据库概述 三 mysql介绍 四 下载安装 五 mysql软件基本管理 六 初识sql语句 一 数据库管理软件的由来 基于我们之前所学,数据要想永久保存,都是 ...

  5. JS实现焦点图轮播效果

    大家平时逛淘宝网的时候,在首页就能看到焦点图轮播的效果,就是这个样子的: PS:想起每每打开淘宝,总会被这个玩意先夺眼球,偶尔还去点进去溜溜,幸好我定力好,总能控制住自己的购买欲望,为自己不用剁手感到 ...

  6. CEF3开发者系列之CefEnableHighDPISupport详解

    在CEF3中,CefEnableHighDPISupport()这个接口函数在使用时一般不为人所注意,但是如果稍有不慎,会造成打开的网页不能填满窗口的问题.如果是需要flash插件才能运行的游戏.则会 ...

  7. SDN前瞻 传统网络架构的危机:危机“四”起

    本文基于SDN导论的视频而成:SDN导论 在网络发展速度如此之快的今天,传统网络的架构充满了危机,主要有这四个问题(3+1). 1)传统网络的部署和管理 非常困难 2)分布式网络架构凸显瓶颈 3)流量 ...

  8. 使用CAS实现无锁的SkipList

    无锁 并发环境下最常用的同步手段是互斥锁和读写锁,例如pthread_mutex和pthread_readwrite_lock,常用的范式为: void ConcurrencyOperation() ...

  9. 【Jmeter】配置不同业务请求比例,应对综合场景压测

    背景 在进行综合场景压测时,遇到了如何实现不同的请求所占比例不同的问题. 有人说将这些请求分别放到单独的线程组下,然后将线程组的线程数按照比例进行配置. 这种方法不是很好,因为服务器对不同的请求处理能 ...

  10. 不能用Xming连接到 Centos 7

    修改/etc/gdm/custom.conf 之后, Centos 6是没有问题的. 可是Centos 7 不行. 根据这个连接,运行firewall-config,把网络改到trusted级别, 能 ...