网站首页 > 精选教程 正文
针对移位(Shift Operator)操作符是最基本的操作符之一,几乎每种编程语言都包含这一操作符。
同时我们对移位运算又会觉得比较陌生和困惑,这是因为移位运算除了在 JDK 底层你会遇到不少,还有就是在各种奇葩的面试题会遇到一些,在实际使用的时候,这个运算其实很难用得上。
因为用得不多,所以在大部分人的面对的代码情况下,根本不会考虑移位运算,所以对移位运算我们大致知道下就可以了,至于如何奇葩的运算,你只知道一些基本概念就行,其实很多时候并不需要你直接用移位运算算出来。
基本概念
针对移位运算,我们需要了解有几个基本概念。
3 个移位运算符
Java 只有 3 个移位运算符, << (左移)、 >> (带符号右移)和 >>> (无符号右移)。
为什么有 3 个,移位运算不是左就是右,为什么有 3 个?
因为 Java 的整数是有符号的整数,所以针对符号转换 Java 添加了一个无符号右移。
只能用于整数
Java 的移位运算,不能用于浮点数,只能用于整数。
因为 Java 可以处理整数的长度不一样,所以移位运算只会用在 int 上,虽然其他数据类型也可以用,但是都是在转换成 int 后进行计算的。
类型 | 长度 |
long | 64 位 |
int | 32 位 |
short | 16 位 |
byte | 8 位 |
char | 8 位 |
整数 2 进制表达
在 Java 的整数 int 表达中,其中有一个位留给了符号位置,所以真正可以存储数据的位为 31 位。
因此,Int 的存储范围为:[-2^31,2^31-1],所以上面的指数为 31, 而不是 32 的原因是其中有一位留给了符号位。
左移操作符 <<
左移操作符 << 是将数据转换成二进制数后,向左移若干位,高位丢弃,低位补零 。
如下面的代码:
log.debug("{}/{}", Integer.toBinaryString(12), Integer.parseInt(Integer.toBinaryString(12), 2));
log.debug("{}/{}", Integer.toBinaryString(12 << 1), Integer.parseInt(Integer.toBinaryString(12 << 1), 2));
log.debug("{}/{}", Integer.toBinaryString(12 << 8), Integer.parseInt(Integer.toBinaryString(12 << 1), 2));
程序的输出为:
12:16:18.985 [main] DEBUG com.ossez.toolkits.codebank.tests.EmptyQuickTest - 1100/12
12:16:18.986 [main] DEBUG com.ossez.toolkits.codebank.tests.EmptyQuickTest - 11000/24
12:16:18.986 [main] DEBUG com.ossez.toolkits.codebank.tests.EmptyQuickTest - 110000000000/24
因为都在末尾补 0 ,所以在范围内,不管你是左移 1 位还是超过 1 位,都是等于 10 进制的数乘以 2。
带符号右移操作符 >>
Java中整型表示负数时,最高位为符号位,正数为0 ,负数为1 。
>> 是带符号的右移操作符,将数据转换成二进制数后,向右移若干位,高位补符号位,低位丢弃 。
对于正数作右移操作时,具体体现为高位补0 ;负数则补1
这个主要是针对右移动的时候高位出现空白,我们应该还是补 0 还是 1 的问题。
带符号的右移意思就是:当高位出现空白的时候,我们补符号位,根据当前的数据不同而不同。
如下面的代码:
log.debug("{}", Integer.toBinaryString(-12));
log.debug("{}", Integer.toBinaryString(-12 >> 1));
log.debug("{}", Integer.toBinaryString(-12 >> 8));
运行结果为:
12:25:32.765 [main] DEBUG com.ossez.toolkits.codebank.tests.EmptyQuickTest - 11111111111111111111111111110100
12:25:32.765 [main] DEBUG com.ossez.toolkits.codebank.tests.EmptyQuickTest - 11111111111111111111111111111010
12:25:32.765 [main] DEBUG com.ossez.toolkits.codebank.tests.EmptyQuickTest - 11111111111111111111111111111111
我们可以看到上面的移位为带有符号的移位置,所有移动的高位在负数的时候都被补充为符号位了。
如果是负数的话,就会补充为 1 。
无符号右移操作符 >>>
无符号右移操作符 >>> 与>> 类似,都是将数据转换为二进制数后右移若干位,不同之处在于,不论负数与否,结果都 是高位补零,低位丢弃 。
这个操作符的计算对负数的计算会因为补位的不同而变成整数。
如下面的代码。
log.debug("---- Shift Operator >>> ---");
log.debug("{}", Integer.toBinaryString(-12));
log.debug("{}/{}", Integer.toBinaryString(-12 >>> 1), Integer.parseInt(Integer.toBinaryString(-12 >>> 1), 2));
log.debug("{}/{}", Integer.toBinaryString(-12 >>> 8), Integer.parseInt(Integer.toBinaryString(-12 >>> 8), 2));
程序输出如下:
13:25:19.374 [main] DEBUG com.ossez.toolkits.codebank.tests.EmptyQuickTest - ---- Shift Operator >>> ---
13:25:19.374 [main] DEBUG com.ossez.toolkits.codebank.tests.EmptyQuickTest - 11111111111111111111111111110100
13:25:19.374 [main] DEBUG com.ossez.toolkits.codebank.tests.EmptyQuickTest - 1111111111111111111111111111010/2147483642
13:25:19.374 [main] DEBUG com.ossez.toolkits.codebank.tests.EmptyQuickTest - 111111111111111111111111/16777215
从上面的代码输出中,我们会发现对应的 2 进制长度不一样,因为在 Java 程序中对于二进制,前面为 0 的时候,在输出的时候会进行丢弃的。
所以显示的长度不一样,如果希望显示长度一致的话,前面补 0 就可以了。
- 上一篇: Java中字符串填充零和去零的常用方法
- 下一篇: Java教程:3种位移运算符详解
猜你喜欢
- 2025-01-13 Java内存溢出的解决思路
- 2025-01-13 Android应用编程基础第18篇:Java面向对象技术点补
- 2025-01-13 图文详解,史上最详细JVM——字节码指令集
- 2025-01-13 盘点 Java 开发 2020 年发生的几件大事
- 2025-01-13 全网最完整的免费java教程讲义(一)——java配置和安装
- 2025-01-13 这篇 Java IO,讲的实在是太好了
- 2025-01-13 你真的了解JAVA中对象和类、this、super和static关键字吗
- 2025-01-13 Java单向代码执行链配合的动态代码上下文执行
- 2025-01-13 「景哥java」搞懂java的运算符
- 2025-01-13 SpringBoot必须掌握的常用注解!
你 发表评论:
欢迎- 07-10动漫人物像|插画 壁纸 头像 签名 素材
- 07-10运动人物|插画 壁纸 头像 签名 素材
- 07-10动漫人物|插画 壁纸 头像 签名 素材
- 07-10神话人物|插画 壁纸 头像 签名 素材
- 07-10日漫人物像|插画 壁纸 头像 签名 素材
- 07-10 日漫人物|插画 壁纸 头像 签名 素材
- 07-10日漫人物风|插画 壁纸 头像 签名 素材
- 07-10日漫人物|插画 壁纸 头像 签名 素材
- 最近发表
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)