Java入门必看!Java运算符(超详细)
“这里是offer学堂,帮你轻松拿offer”
嗨~ 今天的你过得还好吗?
明天就是周六啦!
所以今天最重要的任务就是等下班!
又一波干货来袭!
速速收藏!
❤
– 2023.03.17 –
不知不觉又到周五啦,大家是不是都在计划周末去哪儿玩?计划赶不上变化,不如先来看看小编今天分享的内容吧!今天给大家整理了超详细的Java运算符知识,啥也不说了快收藏吧!
运算符就是一种告诉编译器执行特定的数学或逻辑操作的符号,用来表示针对数据的特定操作,也称之为操作符。
在Java当中,运算符可以分为:算术运算符、 关系运算符、逻辑运算符、位运算符、移位运算符以及条件运算符等。下面我们详细看一下每种运算符是怎样的,以及部分使用案例:
注意点:
(1)这些运算符都是二元运算符,使用时必须要有左右两个操作数。
(2)同C语言一样,int / int的结果还是int,而且会向下取整。
要出现小数点,那就转成double类型或在最后*1.0。
(3)除法和取模操作时,右操作数不能为0,否则会报出异常。
(4)%在Java中不但可以对整数进行取模,还可以对double进行取模操作。
(5)两边操作数不相同的时候,会发生类型提升。这个我们来看一个特例:
如图:对两个short类型进行相加,再用short进行接受,发现报错,提示是从int到short可能会有损失。为了计算的方便,Java在将小于4个字节的类型进行计算的时候,会将其隐形提升到int类型。上面两个short均被提升到int,在用short接收,就会报错。解决办法是进行强制类型转换。
该种类型运算符操作完成后,会将操纵的结果赋值给左操作数。要注意只有变量才可以使用该运算符,常量不允许被修改,不能使用。
这两种运算符有前置和后置之分。如果是单独使用,那么前置和后置是没有区别的,如果是混合使用:
混合使用,【前置++】先+1,然后使用变量+1之后的值,【后置++】先使用变量原来的值,表达式结束时给变量+1 只有变量才能使用自增/自减运算符,常量不能使用,因为常量不允许被修改。
主要有六个: ==(等于)、 !=(不等于)、 >(大于)、 >=(大于等于)、<(小于)、<=(小于等于) ,其计算结果是 true 或者 false 。在Java中,只有true和false,不存在0表示假,非0表示真。
当需要多次判断时,不能连着写,比如:3 < a < 5,在C语言当中,是可以运行的,但是在Java当中会报错,需要写成3 <
逻辑运算符主要有:&(按位与),&&(短路与),|(按位或),||(短路或),!(非,即取反)。
短路与&& 和 逻辑与 &有什么区别?
首先这两个运算符的运算结果没有任何区别,完全相同。只不过“短路与&&”会发生短路现象。
什么是短路现象呢?
右边表达式不执行,这种现象叫做短路现象。
什么时候使用&&,什么时候使用& ?
从效率方面来说,&&比&的效率高一些。因为逻辑与&不管第一个表达式结果是什么,第二个表达式一定会执行。
在以后的开发中,短路与&&和逻辑与还是需要同时并存的。大部分情况下都建议使用短路与&&只有当既需要左边表达式执行,又需要右边表达式执行的时候,才会选择逻辑与&。
跟短路与类似
- 使用短路与 && 的时候,当左边的表达式为false的时候,右边的表达式不执行
- 使用短路或 || 的时候当左边的表达式结果是true的时候,右边的表达式不执行
注意:逻辑运算符两边要求都是布尔类型,并且最终的运算结果也是布尔类型。
数据存储的最小单位是字节,而数据操作的最小单位是比特位。字节是最小的存储单位,每个字节是由8个二进制比特位组成的,多个字节组合在一起可以表示各种不同的数据。位运算表示按照二进制的每一位进行运算。
如果两个二进制位都是 1,则结果为 1,否则结果为 0。
如果两个二进制位有一个是1,则结果是1,否则都是0,结果是0。
如果两个二进制位相同,则结果是0,否则是1。
如果该二进制位是1,则变成0,是0,变成1。
Java和C语言不同的地方在于,Java多了一个>>>,表示无符号右移。Java的移位运算符有三个: <<、>>、>>> 。都是二元运算符,且都是按照二进制比特位来运算的。
- 左移:<<最左侧位不要了,在最右侧补零。左移 1 位,相当于原数字 * 2。左移 N 位,相当于原数字 * 2 的N次方。
- 右移:>>最右侧不要了,在最左侧如果是正数,补0,负数补1。右移 1 位,相当于原数字 / 2。右移 N 位,相当于原数字 / 2 的N次方。
- 无符号右移:>>>最右侧位不要了,最左侧补0。
- 移动负数位或者移位位数过大都没有意义。
计算机在进行运算的时候,实际上是按照二进制运算的。加减等在运算的时候被转化成二进制的形式进行运算。计算机计算移位效率高于计算乘除,比如当某个代码正好乘除 2 的N次方的时候可以用移位运算代替。有的时候,可以拿来用用。比如求两个数的平均值:
条件运算符只有一个:表达式1: 表达式2 : 表达式3。
当表达式1为true时,执行表达式2,表达式3不在执行,否则执行表达式2。这个是Java当中唯一的一个三目运算符。
表达式2和表达式3的结果需要同类型的,表达式不能单独存在。
看到图中这么多内容,是不是头都大了,其实不必记忆,在使用的时候直接加括号就可以了。
今天的分享就到这里了,想了解更多编程知识,记得常来看我!
我们下期再见!
END
文案编辑|云端学长
文案配图|云端学长
内容由:云端源想分享
我们必须要了解的Java位运算(不仅限于Java)
1、当前常见的CPU位数是32位和64位,所谓32位处理器就是一次只能处理32位,也就是4个字节的数据,而64位处理器一次则能处理64位,即8个字节的数据。
2、一字节(1Byte)等于8位(8bit),位是计算机存储数据的最小单位,也就是计算存储的数据是一系列二进制位信息。每个位用0或1表示。(大B和小b的区别需注意哦)
3、为什么一个字节是8位?现在通用的说法是8位可以涵盖所有的字符编码,即ASCII编码。但历史上也存在过4位或者7位为1Byte的场景,只是在后续的字符集标准统一中逐渐被8bit所替代。除了历史原因之外,还有数据存储的需要(必须要能在一个字节内表示超过100种状态,包括常用数字,大小写字母等),再加上早期计算机存储价格昂贵,所以8bit也是在当时符合二进制特性的必然结果。
4、二进制加减运算,加法:0+0=0,0+1=1,1+0=1,1+1=10 ,逢2进1。
5、二进制转十进制及十进制转二进制。
上述列出了一些基本概念和对应的可参考链接,建议先优先了解一下。尤其是二进制和十进制的互相转换以及二进制的加减法规则,在后面都会具体涉及到。
人类用十进制完全是因为我们有10个手指头。如果有一天你看到一个外星人,它只有4个手指头,那么他使用的一定是四进制,如图所示:
如果能看明白上图,说明你已经明白了进制和手指头的关系了。现代的计算机内部使用门电路,它们只能表示0或者1两个状态。如果计算机是一个人,那么他只有两个手指头,所以它使用二进制。是的,就是这样,所谓的进制,实际上并不是什么神秘的东西,只是关于数的一种表示方式而已了。门电路概念
机器数分为:无符号数和有符号数两种。
一个数在计算机中的二进制表示形式, 叫做这个数的机器数。机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0,负数为1。
比如,十进制中的数 +3 ,计算机字长为8位,转换成二进制就是00000011。
如果是 -3 ,就是 10000011 。那么,这里的 00000011 和 10000011 就是机器数。
因为第一位是符号位,所以机器数的形式值就不等于真正的数值。
例如上面的有符号数 10000011,其最高位1代表负,其真正数值是 -3 而不是形式值131(10000011转换成十进制等于131)。
所以,为区别起见,将带符号位的机器数对应的真正数值称为机器数的真值。
例:0000 0001的真值 = +000 0001 = +1,1000 0001的真值 = –000 0001 = –1
为了妥善的处理数据运算过程中符号位的问题,于是就产生了把符号位和数值位一起编码起来表示相应的数的各种表示方法。例如我们熟悉的原码、反码、补码、移码等。通常将未经编码的数称为真值,编码后的数称为机器数或者机器码。
计算机当前所使用的机器数是采用的补码的方式。在探求为何机器要使用补码之前, 让我们先了解原码, 反码和补码的概念。对于一个数, 计算机要使用一定的编码方式进行存储, 原码, 反码, 补码是机器存储一个具体数字的编码方式。
原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值. 比如如果是8位二进制:
第一位是符号位. 因为第一位是符号位, 所以8位二进制数的取值范围就是:
转换为真值后即:
原码是人脑最容易理解和计算的表示方式。原码也可以理解为最原始的机器码。
反码的表示方法是:正数的反码是其本身,负数的反码是在其原码的基础上, 符号位不变,其余各个位取反。
可见如果一个反码表示的是负数, 人脑无法直观的看出来它的数值. 通常要将其转换成原码再计算。
补码的表示方法是:正数的补码就是其本身,负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)。
对于负数, 补码表示方式也是人脑无法直观看出其数值的. 通常也需要转换成原码在计算其数值。
注意:我们在最初的基本概念中提到了二进制和十进制的转换方式。但是需要知道的是,一个数在计算机中的二进制表示方式叫做机器数。
而机器数是有符号的,我们将对应的最高位存放符号,0位正数,1位负数。所以机器数并不等于二进制。
由此我们才引出了真值的概念,例如:符号数 10000011,在十进制中对应的值为131,但是在机器数中,由于1表示负数,所以其真正数值是-3,而并不是131。
符号数:10000011,我们需要先消除其符号位的影响,将其调整为正数:00000011,此时将正数转换为10进制为3,然后再加上最初的符号位表示负数,所以为-3。
需知道的是,二进制仅是以2为基数的计数方式而已,在二进制中是无法区分正数和负数的。而如果想区分正数和负数那么必须在二进制的最高一位中用0和1来表示符号以此来表示正负。那么此时最高位的0和1已经不是二进制的一种计数方式了,而只是一种符号的标识,该符号的标识则是万万不可以直接参与二进制的计算的。
当我们用最高位中的0和1来表示正负时,此时该二进制的数已经不再是符合二进制规则的数了,而是机器数。
二进制仅仅是以2为基数的计算方式,此时最高位的值已经不再是通过2位基数的计算方式而计算出来的,而只是一个表示正负的标识了,所以此时该数值则已经不再是符合二进制规则的数了,而是机器数。
所以,也只有机器数才可以表示正负。而机器数所对应得到的结果则是真数,而并不是10进制数。
如果此时抛出来一个问题:10000011 转换为对应的10进制,那么对应的结果则是131,但如果是转换为真数,则是-3。同样的,如果是将00000011 转换为对应的10进制,则是3,而如果转换为真数,则也是3。
所以当我们看到一个以8位数所表示的二进制数时,则一定要确认该二进制数是表示机器数,还是二进制数?是转换为10进制数,还是真数。其中最大的区别则是,最高的符号位到底是参与二进制的运算,还是仅仅表示符号位。
机器数转真数:10000011 >消除最高位1的影响先转为正数>00000011>再将该正数以二进制的方式转为十进制为> 3 >此时再将最初的符号添加回来>3调整为-3。
二进制数转10进制数:10000011 >无需消除最高位1的影响直接转为正数>10000011>再将该正数以二进制的方式转为十进制为 > 131>无需添加符号位>131仍然为131。
所以可知,真数和10进制数最大的区别则是是否忽略最高位,在确认完是否忽略最高位,得到最初的正数后,该正数的计算方式,则和二进制转十进制的方式完全相同。其实就是二进制转十进制。哈哈。
那么在注意了二进制数和机器数以及十进制数和真数的区别之后。我们则需要注意的另外一个问题则是:
机器数是包含原码、反码、补码。其中三者之间是可以互相转换的。原码转反码转补码,这块上面已经说明过了,而补码则也可以通过想反的方式重新转换为原码。
而此处需要知晓的则是,反码和补码当然是不可以直接转为真数的,而必须要通过原码才可以进行转换。
这个其实也没什么问题,毕竟原码经过层层转换后得到补码,而补码又可以直接转换为真数,当然不可能了。
接下来则是,为什么原码需要转换为补码,为什么原码不是计算机的计算方式,而是补码?
本文原创地址为 https://www.cnblogs.com/zh94/p/16195373.html
原创声明:作者:陈咬金、 博客地址:https://www.cnblogs.com/zh94/
现在我们知道了计算机可以有三种编码方式表示一个数. 对于正数因为三种编码方式的结果都相同:
所以不需要过多解释. 但是对于负数:
可见原码, 反码和补码是完全不同的. 既然原码才是被人脑直接识别并用于计算表示方式, 为何还会有反码和补码呢?
首先, 因为人脑可以知道第一位是符号位, 在计算的时候我们会根据符号位, 选择对真值区域的加减。但是对于计算机, 加减乘数已经是最基础的运算, 要设计的尽量简单. 计算机辨别\”符号位\”显然会让计算机的基础电路设计变得十分复杂! 于是人们想出了将符号位也参与运算的方法. 我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了。
于是人们开始探索 将符号位参与运算, 并且只保留加法的方法. 首先来看原码:计算十进制的表达式: 1-1=0
如果用原码表示, 让符号位也参与计算, 显然对于减法来说, 结果是不正确的.这也就是为何计算机内部不使用原码表示一个数。为了解决原码做减法的问题, 出现了反码:计算十进制的表达式: 1-1=0
发现用反码计算减法, 结果的真值部分是正确的. 而唯一的问题其实就出现在\”0\”这个特殊的数值上. 虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 而且会有[0000 0000]原和[1000 0000]原两个编码表示0。
于是补码的出现, 解决了0的符号以及两个编码的问题:
这里说明一下,二进制想加:0000 0001+1111 1111 = 1 0000 0000,但由于是8位数,所以最终的值为 0000 0000。
这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128:
由于我们使用原码来表示正时,最大值为:01111111,最小值为:11111111,所以直接转换为对应的10进制后的结果为,127,-127。而此处使用补码后,由于补码的规则是,首位不变,其它反转,并+1。所以(-1)+(-127) 刚好为-128。
使用补码, 不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数. 这就是为什么8位二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127]。
因为机器使用补码, 所以对于编程中常用到的32位int类型, 可以表示范围是: [-2的31次方, 2的31次方 – 1] 因为第一位表示的是符号位.而使用补码表示时又可以多保存一个最小值。
Amazing,我们在上面最初使用原码进行加法运算时,由于我们人脑还需要先判断一下最高位的符号后,才能进行二进制运算,然后再添加上对应的符号位。而采用补码后,直接将对应的符号位也参与运算,将补码的数值直接相加,得到的竟然刚好也就是二进制转换后的结果。这样一来,计算机的基础电路设计就可以更加简单,而无需关注符号位的问题,仅需要按照二进制的加法法则执行即可。简直完美。所以这也是补码作为计算机的真正计算方式的原因之一!
但,补码后所得到的值想加刚好就是直接二进制的值相加后的结果,真的是就刚好这么巧吗?其实不然,背后还蕴含这很有意思的数学原理,详情可参考:深入理解原码、补码 & 数的机器码表示 & 机器码原理 & 原码、补码原理
文章最顶部基本概念处列到了“10进制2进制互转”,以及“2进制加减法”对应的相关链接。此处再推荐几个在线计算的网址,便于将自己的计算结果进行二次验证:在线原码、补码、10进制互转 & 在线进制转换 & 在线二进制加减法
接下来则开始涉及到位运算了。
什么是位运算?我们先来看下百度百科的概念:
百度百科中所给的解释是具备歧义性的,按照百度百科的解释,直接对整数在内存中的二进制位进行操作就是位运算的话,那么使用二进制数进行算术运算法(+,-,*,/ )岂不是也属于位运算?
我们再来看下维基百科所给的概念解释:
维基百科中针对位运算的概念相对合理,通过维基百科中的概念我们可以很明显的区分到,位运算是和加减乘除这些算数运算符是不同的。不同的CPU针对位运算的操作是较快于(乘/除)法运算的。
所以这也才是我们需要了解位运算的真正原因,那就是CPU处理器针对位运算符的计算是快于算术运算符的!在特定的编码场景下使用位运算的执行速率则是远远大于算术运算的!
程序中的基本运算包含:
- 算术运算:加、减、乘、除、取余
- 按位运算:按位或“|”、按位与“&”、按位取反“~”、按位异或“^”
- 移位运算:左移x<<k;右移x>>k
其中按位运算和移位运算均属于位运算的范畴。
位运算的具体执行逻辑,我们下面会详细说明。这里先以位运算中的 与 运算符 “&” 来简单说明下位运算的主要执行逻辑:& 与运算符的运算规则是:两个位都为1时,则结果为1。如:3&5 即 0000 0011& 0000 0101 = 0000 0001,因此 3&5 的值得1。
根据与运算符的规则可知,位运算的整体执行逻辑实际是较为简单的,更多的是进行位数的比较,从而得到一个结果,这种较为简单的运算逻辑,则对于CPU处理器来说,在电路的设计中则也会更加简单许多,以下为与运算符所涉及到的CPU电路图:
而对于一个除法来说呢,在CPU中所对应的电路图设计则是这样的:
可以看到,整个CPU电路图的设计复杂了不止一个层级,所以这也就是为何位运算比我们人常用的算术运算更快的直接原因了。因为对于整个CPU的执行逻辑来说从设计层面就复杂了很多。
当然,提到CPU的电路图设计,就不得不提到对应的CPU中晶体管的特性了,而晶体管中所涉及到的开关(01)的特性也就构成了逻辑电路,从而构成了与门、或门、非门、异或门等电路特性。这块内容,可以参考如下链接:位运算中隐藏的CPU秘密程序中的位运算于基本电路关系程序中位运算于基本电路-知乎四位计算机的原理及实现位运算的理解程序中的取余是如何实现的二进制乘除法的实现
CPU中的电路设计和数学的算法实现有着很精妙的联系,计算机前辈的力量是无穷的。那到了这里,我们也就知道了程序中基本运算在执行速率上的真正差别实际上是在CPU这一层级的,了解了这些之后,我们也就可以接着开始说明位运算符的真正执行逻辑了。(位运算仅需进行01的比较,和移位等简单的逻辑操作,基本上和直接执行二进制的相加规则一样,在电路设计和逻辑上均更加简单,而乘除求余则在电路的设计中较为复杂)
本文原创地址为 https://www.cnblogs.com/zh94/p/16195373.html
原创声明:作者:陈咬金、 博客地址:https://www.cnblogs.com/zh94/
首先需知道的是,计算机中执行位运算,肯定是采用的补码的方式进行的位计算哦,所以对于真值为负数的情况下,必须先转为补码才能进行计算。
运算规则:两位同时为1,结果才为1,否则结果为0。
例如:2 & -2
注意:负数当然是按照补码的方式来进行位计算哦。
根据与运算符的计算特性,我们常用的使用方式有:1、判断奇偶数我们知道,按照二进制和十进制(除二取余)的换算方式,如果是偶数的情况下,换算为二进制后末位必然是0,如果是奇数则末位为1。比如:2 >10 ,3 > 11,100 >1100100,121 > 1111001。
所以,我们按照与运算符的运算规则,使用 if(a & 1)1表示为奇数,if(a & 1)0,则表示为偶数。如:121 & 1 = 1111001 & 0000001 = 00000012 & 1 =10 & 01 =00
使用与运算符的方式,则完全可以替代掉:if (a % 2 == 0) 来判断奇偶数的方式,且位运算符由于CPU的支持,执行效率也更高。
关于二进制转十进制的方式,参考基本概念中URL即可。
2、取一个数的指定位比如取数 X=1010 1110 高4位,只需要另外找一个数,令 Y的高4位为1,其余位为0,即Y=1111 0000,然后将X和Y进行与运算,(X & Y = 1010 1110 & 1111 0000 = 1010 0000)即可得到X 的指定高4位。
如果想获取X的低4位的数,则将Y的低4位为1,其余位数为0即可,(X & Y=1010 1110 & 0000 1111=0000 1110)便可得到X的指定低4位。
运算规则:两个位都为0时,则结果为0。否则则为1。
例如:2 | -2 =-2
首先与和或是两个相反的概念,所以上述所提到的与的用途,在这里只要略作改造就也适合于或运算符。但是目的是一样的,所以对应相同用途的场景,这里不再赘述。
1、常用来对一个数据的某些位设置为1比如将数 X=1010 1110 的低4位设置为1,只需要另找一个数Y,令Y的低4位为1,其余位为0,即Y=0000 1111,然后将X与Y进行按位或运算(X|Y=1010 1111)即可得到。
同样的,使用 & 运算符,则可以方便的将某些位设置为 0,如上述的X & Y,将X的低4位设置为0,则X & Y = 1010 1110 & 1111 0000 = 1010 0000。
以上则说明 & 和 | 灵活运用,其实是可以达到相同效果的。但实际使用中则并不然,首先对于上述低4位设置为1的场景,我们只需要找一个Y的数,令Y的低4位为1,其余位为0,这样一个数是很好找的,是一个固定的数,比如:15。转换为二进制后为1111。
但如果使用 & 运算符来面对这个场景,则需要找一个Y,Y的第四位为0,其余位置为1,这样一个数则很难找,并且随着位数的不同,值也是不断变换的,比如:1111 0000=240,但如果是12位数,1111 1111 0000=4080。所以如果使用 & 运算符来在该场景下则是没有 | 运算符更加方便的。
尽管 & 和 | 的规则相反,可灵活变更,但针对特定场景下,还是使用特定的运算符效果更佳O。
运算规则:两个位相同为0,相异为1。
例如:2 ^ -2
1、交换两个数
交换两个数的原理,即上面注释所写内容。
不使用位运算的方式交换两个数,则需要定义一个中间变量C,来承接其中的一个数的交换,对于Java来说,定义一个新的Int 变量C,则表示内存中需开辟一个4字节的空间。
所以根据服务特性来选择合适的方式即可,对内存使用率有强要求则使用位运算,没要求则都可以。
运算规则:0变1,1变0。
运算规则:将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。
设 a=15,即二进制数00001111,左移2位得00111100,即十进制数60。
左移一位相当于该数乘以2,左移2位相当于该数乘以2^2=4。上面举的例子15<< 2=60,即乘了4。(结论:左移n位等于乘以2的n次方)
设 a=-46,补码后为,1010 1110,a = a<< 2 将a的二进制位左移2位、右补0,即得a=1011 1000,转换为真值后为-56。
设 a=110,补码后为:0110 1110,a = a<<2 将a 的二进制位左移2位,右补0,即得 a=1011 1000,转换为真值后为184。
以此可知,左移n位等于乘以2的n次方,该结论仅适用于该数左移时被溢出舍弃的高位中不包含1的情况,如果溢出的高位中包含1,则不符合上述结论。
运算规则:将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。例如:a=a>>2 将a的二进制位右移2位,左补0 或者 左补1需要看被移数是正还是负。
设 a=16,补码后为00010000,a = a<<2 将a的二进制位右移2位,左边补0,即得a=00000100,转换为真值后为4。
设a=-16,补码后为11110000,a = a<<2 将a的二进制位右移2位,左边补1,得到a=11111100,转换真值后为-4。
结论:右移运算符,操作数每右移一位,相当于该数除以2。
本文原创地址为 https://www.cnblogs.com/zh94/p/16195373.html
原创声明:作者:陈咬金、 博客地址:https://www.cnblogs.com/zh94/
位运算本身就是处理器、计算机自身所提供的能力,所以针对位运算的使用,实际上是不限于任何编程语言的,此处之所以以JAVA为例,主要是因为本人常用的开发语言是JAVA,哈哈。
针对JAVA中位运算的使用,实际上在JDK中有这很丰富的案例,比如:
1、JDK中线程池ThreadPoolExecutor的实现当中使用Integer类型(4字节,32位)其中高3位保存线程池状态,而低29位保存线程池内有效线程数量。
2、比如JDK的HashMap中使用位运算的方式将初始化容量的数值,快速的转换为2的n次幂。以及计算key的hash时,根据该key的hashCode结果,再将该hashCode的高16位和低16位通过位运算的方式进行混合,以此降低hash碰撞的概率等等。
3、比如我们直接打开常用的Integer类的源码,也会发现里面有大量的位运算的使用。
此处仅是为了通过上述举例的方式来以此说明位运算在Java生态中的使用程度,实际上是非常丰富的,并且由于位运算独特的计算特性,在某些相对特殊的代码场景下,使用位运算会意想不到的将问题给简单化。
如果想了解更多在JAVA中的使用场景和案例,建议大家直接翻看各种源码即可。
以上是一些举例,以下再做一些小的补充说明:
在Java当中的位运算,是只针对Int类型和Long类型有效(java中,一个int的长度始终是32位,也就是4个字节,它操作的都是该整数的二进制数,Long则是64位,表示8字节。),而对于byte,char,short,当为这三个类型时,JVM会先把他们转换为Int类型后再进行操作。
使用 toBinaryString() 可以将对应的十进制转为对应的补码。
如上代码可知,Integer和Long转换为补码时,Integer为32位,Long是64位。实际上上述的基本类型32位还是64位,均是直接定义在源码当中的,感兴趣直接看对应的Integer和Long的源码即可。
以下参考链接,仅供参考,部分链接中的内容,可能会具备一些歧义,请读者自行分辨。
祝福各位读者所有看到的知识,都可以最终成为自己的知识!撒花!✿✿ヽ(°▽°)ノ✿!
位运算教程位运算介绍java位运算位运算技巧位运算常用方式
Java 中的移位运算符(Shift Operator)
针对移位(Shift Operator)操作符是最基本的操作符之一,几乎每种编程语言都包含这一操作符。
同时我们对移位运算又会觉得比较陌生和困惑,这是因为移位运算除了在 JDK 底层你会遇到不少,还有就是在各种奇葩的面试题会遇到一些,在实际使用的时候,这个运算其实很难用得上。
因为用得不多,所以在大部分人的面对的代码情况下,根本不会考虑移位运算,所以对移位运算我们大致知道下就可以了,至于如何奇葩的运算,你只知道一些基本概念就行,其实很多时候并不需要你直接用移位运算算出来。
针对移位运算,我们需要了解有几个基本概念。
Java 只有 3 个移位运算符, << (左移)、 >> (带符号右移)和 >>> (无符号右移)。
为什么有 3 个,移位运算不是左就是右,为什么有 3 个?
因为 Java 的整数是有符号的整数,所以针对符号转换 Java 添加了一个无符号右移。
Java 的移位运算,不能用于浮点数,只能用于整数。
因为 Java 可以处理整数的长度不一样,所以移位运算只会用在 int 上,虽然其他数据类型也可以用,但是都是在转换成 int 后进行计算的。
在 Java 的整数 int 表达中,其中有一个位留给了符号位置,所以真正可以存储数据的位为 31 位。
因此,Int 的存储范围为:[-2^31,2^31-1],所以上面的指数为 31, 而不是 32 的原因是其中有一位留给了符号位。
左移操作符 << 是将数据转换成二进制数后,向左移若干位,高位丢弃,低位补零 。
如下面的代码:
程序的输出为:
因为都在末尾补 0 ,所以在范围内,不管你是左移 1 位还是超过 1 位,都是等于 10 进制的数乘以 2。
Java中整型表示负数时,最高位为符号位,正数为0 ,负数为1 。
>> 是带符号的右移操作符,将数据转换成二进制数后,向右移若干位,高位补符号位,低位丢弃 。
对于正数作右移操作时,具体体现为高位补0 ;负数则补1
这个主要是针对右移动的时候高位出现空白,我们应该还是补 0 还是 1 的问题。
带符号的右移意思就是:当高位出现空白的时候,我们补符号位,根据当前的数据不同而不同。
如下面的代码:
运行结果为:
我们可以看到上面的移位为带有符号的移位置,所有移动的高位在负数的时候都被补充为符号位了。
如果是负数的话,就会补充为 1 。
无符号右移操作符 >>> 与>> 类似,都是将数据转换为二进制数后右移若干位,不同之处在于,不论负数与否,结果都 是高位补零,低位丢弃 。
这个操作符的计算对负数的计算会因为补位的不同而变成整数。
如下面的代码。
程序输出如下:
从上面的代码输出中,我们会发现对应的 2 进制长度不一样,因为在 Java 程序中对于二进制,前面为 0 的时候,在输出的时候会进行丢弃的。
所以显示的长度不一样,如果希望显示长度一致的话,前面补 0 就可以了。
本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com
文章为作者独立观点不代本网立场,未经允许不得转载。