在阅读源码的过程中,经常会看到这些符号<< ,>>,>>>,这些符号在Java中叫移位运算符,在写代码的过程中,虽然我们基本上不会去写这些符号,但需要明白这些符号的运算原理,比如HashMap中有以下代码:

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;//左移
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);//无符号右移
}

上段代码中就包含左移运算符<<,无符号右移运算符>>>。这篇文章详细说一下这三个符号:

1、左移运算符:<<

先随便定义一个int类型的数int,十进制的value = 733183670,转换成二进制在计算机中的表示如下:

value << 1,左移1位

左移1位后换算成十进制的值为:1466367340,刚好是733183670的两倍, 有些人在乘2操作时喜欢用左移运算符来替代。

value << 8,左移8位看一下:

左移8位后变成了十进制的值为:-1283541504,移动8位后,由于首位变成了1,也就是说成了负数,在使用中要考虑变成负数的情况。

根据这个规则,左移32位后,右边补上32个0值是不是就变成了十进制的0了?答案是NO,当int类型进行左移操作时,左移位数大于等于32位操作时,会先求余(%)后再进行左移操作。也就是说左移32位相当于不进行移位操作,左移40位相当于左移8位(40%32=8)。当long类型进行左移操作时,long类型在二进制中的体现是64位的,因此求余操作的基数也变成了64,也就是说左移64位相当于没有移位,左移72位相当于左移8位(72%64=8),写一段代码来测试一下

int intValue = 733183670;//随意写一个数
System.out.println("intValue:" + (intValue));//打印intValue
System.out.println("intValue左移1位:" + (intValue << 1));//左移1位
System.out.println("intValue左移8位:" + (intValue << 8));//左移8位
//当int类型左移位数大于等于32位操作时,会先求余后再进行移位操作
System.out.println("intValue左移32位:" + (intValue << 32));//求余为32%32=0,相当于左移0位(不移位)
System.out.println("intValue左移40位:" + (intValue << 40));//求余为40%32=8,相当于左移8位
System.out.println("intValue左移64位:" + (intValue << 64));//求余为64%32=0,相当于左移0位(不移位) long longValue = 733183670L;
System.out.println("longValue:" + (longValue));//打印longValue
System.out.println("longValue左移1位:" + (longValue << 1));//左移1位
System.out.println("longValue左移8位:" + (longValue << 8));//左移8位
//当long类型左移位数大于等于64位操作时,会先求余后再进行移位操作
System.out.println("longValue左移64位:" + (longValue << 64));//求余为64%64=0,相当于左移0位(不移位)
System.out.println("longValue左移72位:" + (longValue << 72));//求余为72%64=8,相当于左移8位
System.out.println("longValue左移128位:" + (longValue << 128));//求余为128%64=0,相当于左移0位(不移位)

看一下结果:

由于double,float在二进制中的表现比较特殊,因此不能来进行移位操作,报错,编译不过,如下图:

注意:其它几种整形byte,short移位前会先转换为int类型(32位)再进行移位,这里就不写代码测试了,大家有兴趣可自行测试。

综上所述:左移 << 其实很简单,也就是说丢弃左边指定位数,右边补0。

2、右移运算符:>>

还是这个数:733183670

value >> 1,右移1位

右移1位后换算成十进制的值为:366591835,刚好是733183670的1半, 有些人在除2操作时喜欢用右移运算符来替代

value >> 8,右移8位看一下

写一段代码测试一下

int intValue = 733183670;//随意写一个数
System.out.println("intValue:" + (intValue));//打印intValue
System.out.println("intValue右移1位:" + (intValue >> 1));//右移1位
System.out.println("intValue右移8位:" + (intValue >> 8));//右移8位
//当int类型右移位数大于等于32位操作时,会先求余后再进行移位操作
System.out.println("intValue右移32位:" + (intValue >> 32));//求余为32%32=0,相当于右移0位(不移位)
System.out.println("intValue右移40位:" + (intValue >> 40));//求余为40%32=8,相当于右移8位
System.out.println("intValue右移64位:" + (intValue >> 64));//求余为64%32=0,相当于右移0位(不移位) long longValue = 733183670L;
System.out.println("longValue:" + (longValue));//打印longValue
System.out.println("longValue右移1位:" + (longValue >> 1));//右移1位
System.out.println("longValue右移8位:" + (longValue >> 8));//右移8位
//当long类型右移位数大于等于64位操作时,会先求余后再进行移位操作
System.out.println("longValue右移64位:" + (longValue >> 64));//求余为64%64=0,相当于右移0位(不移位)
System.out.println("longValue右移72位:" + (longValue >> 72));//求余为72%64=8,相当于右移8位
System.out.println("longValue右移128位:" + (longValue >> 128));//求余为128%64=0,相当于右移0位(不移位)

结果:

和左移一样,int类型移位大于等于32位时,long类型大于等于64位时,会先做求余处理再位移处理,byte,short移位前会先转换为int类型(32位)再进行移位。以上是正数的位移,我们再来看看负数的右移运算,如图,负数intValue:-733183670的二进制表现如下图:

右移8位,intValue >> 8

综上所述:右移运算符>>的运算规则也很简单,丢弃右边指定位数,左边补上符号位。

3、无符号右移运算符:>>>

无符号右移运算符>>>和右移运算符>>是一样的,只不过右移时左边是补上符号位,而无符号右移运算符是补上0,也就是说,对于正数移位来说等同于:>>,负数通过此移位运算符能移位成正数。以-733183670>>>8为例来画一下图

无符号右移运算符>>的运算规则也很简单,丢弃右边指定位数,左边补上0。

摘自https://zhuanlan.zhihu.com/p/30108890

java左移右移运算符详解的更多相关文章

  1. Java的位运算符详解实例——与(&)、非(~)、或(|)、异或(^)

    位运算符主要针对二进制,它包括了:“与”.“非”.“或”.“异或”.从表面上看似乎有点像逻辑运算符,但逻辑运算符是针对两个关系运算符来进行逻辑运算,而位运算符主要针对两个二进制数的位进行逻辑运算.下面 ...

  2. Java:Java的<<<移位运算符详解

    1) 左移运算(<<)       左移就是把所有位向左移动几位 如:   12 << 2    意思就是12向左移动两位 12的二进制是: 0000 1100 通过这个图我们 ...

  3. java左移右移运算符

    http://blog.csdn.net/dandanteng/article/details/7433531 首先要明白一点,这里面所有的操作都是针对存储在计算机中中二进制的操作,那么就要知道,正数 ...

  4. Java基础之 数组详解

    前言:Java内功心法之数组详解,看完这篇你向Java大神的路上又迈出了一步(有什么问题或者需要资料可以联系我的扣扣:734999078) 数组概念 同一种类型数据的集合.其实数组就是一个容器. 数组 ...

  5. Net is as typeof 运行运算符详解 net 自定义泛型那点事

    Net is as typeof 运行运算符详解   概述 在了解运行运算符的前提我们需要了解什么是RTTI ,在任何一门面向对象的语言中,都有RTTI这个概念(即 运行时). RTTI(Run-Ti ...

  6. Java 8 Stream API详解--转

    原文地址:http://blog.csdn.net/chszs/article/details/47038607 Java 8 Stream API详解 一.Stream API介绍 Java8引入了 ...

  7. java反射机制深入详解

    java反射机制深入详解  转自:http://www.cnblogs.com/hxsyl/archive/2013/03/23/2977593.html 一.概念 反射就是把Java的各种成分映射成 ...

  8. 国际化,java.util.ResourceBundle使用详解

    java.util.ResourceBundle使用详解   一.认识国际化资源文件   这个类提供软件国际化的捷径.通过此类,可以使您所编写的程序可以:          轻松地本地化或翻译成不同的 ...

  9. java之StringBuffer类详解

    StringBuffer 线程安全的可变字符序列. StringBuffer源码分析(JDK1.6): public final class StringBuffer extends Abstract ...

随机推荐

  1. Spring Boot 使用 XXL-JOB

    一.配置部署调度中心 1.1 下载源码 https://github.com/xuxueli/xxl-job 1.2 数据库初始化 执行 /xxl-job/doc/db/tables_xxl_job. ...

  2. 图形验证码---pillow

    图片验证码逻辑 客户端发起GET连接请求,并随机生成UUID,绑定图片 UUID:通用唯一识别码(Universally Unique Identifier),目的,是让分布式系统中的所有元素,都能有 ...

  3. 欢迎使用CSDN-markdown编辑器(这个只能看到一次保存一下)

    欢迎使用Markdown编辑器写博客 本Markdown编辑器使用StackEdit修改而来,用它写博客,将会带来全新的体验哦: Markdown和扩展Markdown简洁的语法 代码块高亮 图片链接 ...

  4. python核心高级学习总结6------面向对象进阶之元类

    元类引入 在多数语言中,类就是一组用来描述如何生成对象的代码段,在python中同样如此,但是在python中把类也称为类对象,是的,你没听错,在这里你只要使用class关键字定义了类,其解释器在执行 ...

  5. C#9.0新特性之四:顶级程序语句(Top-Level Programs)

    1 背景与动机 通常,如果只想用C#在控制台上打印一行"Hello World!",这可不是Console.WriteLine("Hello World!"); ...

  6. 第15.43节、PyQt输入部件:QAbstractSpinBox派生类QSpinBox、 QDoubleSpinBox、QDateTimeEdit、QDateEdit和QTimeEdit功能简介

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.概述 Designer输入部件中的Spin B ...

  7. 第15.18节 PyQt(Python+Qt)入门学习:Model/View架构中视图Item Views父类详解

    老猿Python博文目录 老猿Python博客地址 一.概述 在PyQt图形界面中,支持采用Model/View架构实现数据和界面逻辑分离,其中Model用于处理数据存储,View用于界面数据展现,当 ...

  8. Pentaho Report Designer 入门教程(一)

    PentahoReport Designer 入门教程 采用Pentaho Report Designer5.1版本,也是最新的版本. 一.       安装和介绍 介绍部分内容略,首先安装jdk,并 ...

  9. 【软件测试部署基础】npm的认识

    1. npm简介 先来看下官方介绍: npm makes it easy for JavaScript developers to share and reuse code, and it makes ...

  10. Asp.net core中RedisMQ的简单应用

    最近一个外部的项目,使用到了消息队列,本来是用rabbitmq实现的,但是由于是部署到别人家的服务器上,想尽量简化一些,项目中本来也要接入了redis缓存,就尝试使用redis来实现简单的消息队列. ...