运算符这些东西,虽然这些很基础,聪明的人看看解释,或者随便百度些资料就能明白,但是我觉得应该还是有很多像我一样笨的,讲的不详细就迷迷糊糊,不能完全搞懂。本篇有些内容写的比较详细,如有喜欢直接点的哥哥可以通过大纲查看相关内容。
下面开始正文,先看本篇大纲:
①算术运算符: +(加)、-(减)、*(乘)、/(除)、-(负)、+(正) 、 %(取余 )、++(自增(前))、++(自增(后))、--(自减(前))、--(自减(后))
②比较运算符:==(相等于)、!=(不等于)、>(大于)、<(小于)、>=(大于等于)、<=(小于等于)
③逻辑运算符:&(逻辑与)、&&(短路与)、|(逻辑或)、||(短路或)、!(逻辑非)、^(逻辑异或)
④位运算符:<<(左移)、>>(右移)、>>>(无符号右移)、&(与)、|(或)、^(异或运算)、~(取反运算)
算术运算符(一):+(加)、-(减)、*(乘)、/(除)、-(负)、+(正)
这个应该小学就学的很熟练了吧,我就不讲了。
什么?还有人说仔细讲一下?恩..这个吧,三百六十行,行行出状元,不一定非要学软件,还是建议那位要讲一下的同学换个工作(大笑ing)。
不过这里有些注意问题要讲一下;
① /(除) 会保留整数部分,而舍弃小数部分。如 int x=2810; x=x/1000*1000;那么x是多少呢?如果不清楚的哥哥,还是推荐自己敲一下,这样记得才会更清楚(其实撑不了几天又忘了)
② +(加) 当做字符串相加时,会将非字符串转换成字符串。如 System.out.println("3+4="+3+4);,结果是什么?自己敲
算数运算符(二):%(取余 )、++(自增(前))、++(自增(后))、--(自减(前))、--(自减(后))
%(取余) :如果除不尽取余数,数学公式:a%b=a-a/b*b
例: int a=11 ; a=a%3; 那么结果是2;
++(自增(前)):先运算后赋值
例:int a=3; int b=++a; 这里会先算a=a+1 ;然后再赋值给b; 那么 结果 b=4;
++(自增(后)):先赋值后运算
例:int a=3; int b=a++; 这里会先把a赋值给b ,然后再算a=a+1; 那么 结果 b=3;
--(自减(前))、--(自减(后)) 同理,可以自己敲一下
注意:
如果对负数取余,被除数的符号忽略不计,如 11%-3=2;如果除数为负数,则不可忽略,如-11%3=-2。
赋值运算符:= 、+=、-=、*=、/=、%=
=(赋值):
1,当"="两侧数据类型不一致时,可以使用自动类型转换或使用强制类型转换进行处理
2,支持连续赋值
+=、-=、*=、/=、%=
a+=3 --->a=a+3;其他同理
我们对"="详细举例说明一下,这里很有可能涉及到笔试面试题(敲黑板)
①正常赋值:
int a=3; a=3+3;
System.out.println(a);
a+=3;
System.out.println(a);
输出结果 6 , 9;这个应该没什么好说的。
②左右类型不同时 赋值:
先看这几行代码:当int 类型的值和short类型的值相加时,会自动转化成int类型的值;当int 与float类型的值相加时,自动转化成float类型的值,如果将其赋值给较小类型的变量就会报错。说白了就是小弟得听大哥的,跟着大哥出去砸场子,对面让我报名号,我得说大哥是谁,我跟大哥混的,既然是大哥,自然就得有担当,对所有小弟负责。
总结一下:有多种类型的数据混合运算时,会将所有数据转换成容量最大的数据类型,然后计算
当然如果你说10+3又没有出short范围,我就想用short接收,不行吗?(哟,你还有一丝丝小任性)当然可以,这时候加个强制转换就可以了,如下图:
如果用Eclipse等开发的话,可以鼠标放到爆红的地方,会有提示的。场子砸完了,我主动提出 不自量力 要守这片地,大哥也很大方,看到我小子这么上进,就赏我了。所以这个场子归我看了,那我自然就权利大了,对场子老板说,现在这个地方哥哥罩了,以后有人闹事,提我名好使。当你非要强行装逼的时候,就可以加个强制转换。
总结一下:当将范围大的类型转换成范围小的类型时,需要强制转换
关于类型强制转换规则这里只讲一点,就是如果你强行装b,不是自己的非要强转,就会出问题,比如你到人家场地,右脚踩人家桌上,说这片归我管了,如下图:
很明显,我不仅没法占下这个场地,还会被揍一顿。所以不是同一种类型强转是报错的,其他的先不讲,接下来再看:
例:
short s = 3;
s = s + 2;
s += 2;
问: 这两句有什么不同?
第二句会报错,第三句是对的
有的哥哥就一脸黑人问好,我猜他们心情是这样式的:
有几个这样的,举下手手,恩那几个举手的,出去站着去,一看就没好好听。
变量s是short类型的,数字2呢?默认是int型的,那short+int ,很明显会自动转成int,所以结果需要用int接收。那么第三句为什么对呢,因为像+=、-=等符号是有强制转换的,s += 2这句相当于s=(short)(s+2)。哦,原来这样子,那么我们再来看:
例:
short s = 10;
byte b = 3;
s = s + b;(这句对不对?)
char c = 'a';
c + s;(用什么类型接收?)
第一个问题:byte占一个字节,short占两个字节,两个数相加用short接收,会自动转换成大范围的short吗?理是这个理,但这句是错的。
第二个问题:char 类型占两个字节,short也占两个字节,那么他们相加用char接收?用short接收?很明显谁也不服谁,那干脆用int接收吧(固定搭配,背下来)。
总结一下:byte,short,char进行运算时,系统先转换成int,然后计算
其他规则:
整数可以直接给byte,short,char赋值,不能超过相应类型的数据范围
boolean 不能和其他数据类型运算
赋值和算术运算符讲完了,来个题热热身?(很简单,小哥哥不要怕)
告诉我答案?
恩,很对,就是11。 先算a++ ,这个是先赋值,所以仍然是3, ++a 先运算 ,a=4 ;再算a=a+3+4 ,a现在是4,所以结果是11。
比较运算符:==(相等于)、!=(不等于)、>(大于)、<(小于)、>=(大于等于)、<=(小于等于)
比较运算符返回结果都是:true 或 false
这个比较简单,看一下例子:
逻辑运算符:&(逻辑与)、&&(短路与)、|(逻辑或)、||(短路或)、!(逻辑非)、^(逻辑异或)
这个也不是很难,看张图基本就懂了:
有哥哥问了,你说这个独生子"&"跟这个双胞胎"&&"有啥区别?还有 "|" 跟 "||"
"&" 无论左边真假,右边都参与运算
"&&" 如果左边是真,右边参与运算,如果左边是假,右边不参与运算
"|" 无论左边真假,右边都参与运算
"||" 如果左边为真,右边不参与运算
"^" 当左右结果不一样时,返回true
来个题热身:
结果 2 - 1 因为 x++==2为false,所以短路,后边不计算
本篇重点:
位运算符:<<(左移)、>>(右移)、>>>(无符号右移)、&(与)、|(或)、^(异或运算)、~(取反运算)
有的哥哥 看到&、|、^激动了,疯狂举手暗示,这个我知道,我知道
行,那你说一下啥意思,当&左右两边都为true时,返回true,其他为false,当...
行说的挺好,站一会吧,站到下课。不服?待会让你服
位运算符是直接对整数的二进制进行运算,关于二进制,八进制,十进制,十六进制的说明及互相转换,可以看我写的另一篇文章,这里只讲一下几个概念(比较重要,跟后边运算息息相关,不用我说啥了吧,背下来)。
java整数常量默认是int类型,int占4个字节,每个字节有8位,当用二进制定义整数时,第32位是符号位。
二进制整数有如下三种形式:
原码:直接将一个数值换成二进制数,最高位是符号位
负数的反码:对原码按位取反,最高位(符号位)确定为1
负数的补码:其反码加1
正数原码、反码、补码都相同
计算机以二进制补码的形式保存所有整数
举个例子吧:
int a = -3; 那么它是相对应的源码 ,反码,补码是多少呢?
原码:1000 0000 0000 0000 0000 0000 0000 0011 (int类型数据占32位,负数首位是1,3是一个十进制的数,转换成二进制就是 11 ,转换方法可参考我的另一篇文章 ,所以最终就成了上面的样子)
反码:1111 1111 1111 1111 1111 1111 1111 1100 (首位不变,其他位按位取反,就是1变成0,0变成1)
补码:1111 1111 1111 1111 1111 1111 1111 1101 (反码加1,在计算机中-3最终保存形式就是这个样子)
那么我们现在来学习位运算符:
<<(左移): 看这个名称就懂啥意思了,左移------>各位向左移动,空缺位补0,最高位舍弃。
来看个例子:
int a=3 << 3 ----->把3左移三位,
正数3的补码跟原码相同,如下:
0000 0000 0000 0000 0000 0000 0000 0011
开始左移:
000 0 0000 0000 0000 0000 0000 0000 0011 000
左移三位,最前边三位舍弃(删除线部分),舍弃三位,为了保证这个数依然是32位,我们需要再末尾补三位,补位填0,最终结果 :2⁴*1+2³*1+2²*0+2¹*0+2º*0 = 24
这时有个超级聪明的小学僧( 其实是我 )就问了:你说第一位是符号位,如果我向左移动31位,1在符号位上,这时结果变成了啥呢?
先看移动结果:
0000 0000 0000 0000 0000 0000 0000 001 1 0000 0000 0000 0000 0000 0000 0000 000
那结果是: -0 吗?
实际上 :3 << 31 = 0x80000000(十六进制) ,首位是1,说明是个负数 ,那么结果:-2³¹
int值的范围:-2³¹ ~ 2³¹-1, 3<<31 结果其实就是int的最小值
又有个超级聪明的小学僧( 还是我 )问:如果我向左移动32位,33位,108位,结果是啥呢?,是不是都是0?
如果遇到这种不懂的,应该先在eclipse上敲一下,如下:
结果出乎意料,竟然不是0?
实际上,当左移超过31位时,会对移动的位数取余,如果是左移33位,最终移动位数:33%32=1位,所以结果是6,移动108位,最终移动位数:108%32=12位。
接下来,我们对负数左移:负数在计算机中是以补码形式保存的,那么计算根据补码计算,计算完,还原显示
如: -3 << 3
原码:1000 0000 0000 0000 0000 0000 0000 0011 (负数首位是1)
反码:1111 1111 1111 1111 1111 1111 1111 1100 (除首位,其他位取反)
补码:1111 1111 1111 1111 1111 1111 1111 1101 (反码加1)
左移3位: 111 1 1111 1111 1111 1111 1111 1111 1101 000 (最高三位舍弃,尾部添加三位,补0)
还原:
反码:1 1111 1111 1111 1111 1111 1111 1100 111(将左移3位的结果-1)
原码:1 0000 0000 0000 0000 0000 0000 0011 000 (首位不变,其他位取反)
结果: -(2⁴*1+2³*1)= -24 (首位是1,所以是负数)
那个聪明的小学僧又来了,(问题真多,嫌弃脸....he tui) 如果-2左移31位,符号位变成了0,结果是什么呢?
来看左移过程:
原码:1000 0000 0000 0000 0000 0000 0000 0010
反码:1111 1111 1111 1111 1111 1111 1111 1101
补码:1111 1111 1111 1111 1111 1111 1111 1110
左移31位:
1111 1111 1111 1111 1111 1111 1111 111 0 000 0000 0000 0000 0000 0000 0000 0000
反码: 1 111 1111 1111 1111 1111 1111 1111 1111
原码:0000 0000 0000 0000 0000 0000 0000 0000
结果:0
那左移超过32位呢? 跟正数一样取余,左移33位实际上就是33%32=1位
>>(右移) :如果最高位是0,空缺位补0,最高位是1,空缺位补1
正数比较简单,只看个例子:15>>3
15 --> 0000 0000 0000 0000 0000 0000 0000 1111
右移3位:
000 0000 0000 0000 0000 0000 0000 0000 1 111 (加粗的是补位,删除线的是舍弃位)
那么结果 : 1。
负数右移:
-15 >> 3
原码:1000 0000 0000 0000 0000 0000 0000 1111
反码:1111 1111 1111 1111 1111 1111 1111 0000 (首位不变,其他位取反)
补码:1111 1111 1111 1111 1111 1111 1111 0001 (反码加1)
右移3位:
111 1111 1111 1111 1111 1111 1111 1111 0 001 (首位是1,补位补1,尾部三位舍弃)
反码: 111 1111 1111 1111 1111 1111 1111 1110 1 (上边结果-1)
原码:100 0000 0000 0000 0000 0000 0000 0001 0
结果: -2 。
>>>(无符号右移) :不管首位是0是1,补位全都补0
正数没啥好说的,跟>>结果一样,看一下负数
-15 >>> 3:
原码:1000 0000 0000 0000 0000 0000 0000 1111
反码:1111 1111 1111 1111 1111 1111 1111 0000 (首位不变,其他位取反)
补码:1111 1111 1111 1111 1111 1111 1111 0001 (反码加1)
无符号右移3位:
000 1111 1111 1111 1111 1111 1111 1111 0 001 (无符号右移补位补0,尾部三位舍弃)
这里注意,因为首位不是1,所以就不是负数,无需再算补码,原码了,正数原码补码相同
所以结果: 2²⁹-2=536870910 。
有个哥哥说你说等于这个就是这个,证据呢?
直接看测试代码吧:
哼,这次信了吧
&(位与运算):只有1&1结果是1,其他为0
直接来个复杂点的例子吧:-18&-13
-18原码: 1000 0000 0000 0000 0000 0000 0001 0010
反码: 1111 1111 1111 1111 1111 1111 1110 1101
补码: 1111 1111 1111 1111 1111 1111 1110 1110
-13原码: 1000 0000 0000 0000 0000 0000 0000 1101
反码: 1111 1111 1111 1111 1111 1111 1111 0010
补码: 1111 1111 1111 1111 1111 1111 1111 0011
-18&-13
1111 1111 1111 1111 1111 1111 1110 1110
&
1111 1111 1111 1111 1111 1111 1111 0011
=
1111 1111 1111 1111 1111 1111 1110 0010
反码:1111 1111 1111 1111 1111 1111 1110 0001
原码:1000 0000 0000 0000 0000 0000 0001 1110
结果: -(2⁴*1+2³*1+2²*1+2¹*1) = -30
有个哥哥又不信,你能演示一下嘛?ok,看图
使用场景:
①清零,如果想将一个单元清零,只要与一个各位都是零的数值相与,结果为零。
②取一个数中 指定 位:取一个数中 指定位置值,只需要跟一个数做与运算,该数的对应位为1,其余位为零,此数与x进行“与运算”可以得到x中的指定位
例如:我想获取10101110低四位,用10101110&0000 1111=0000 1110即可得到。
|(位或运算):只有0|0时结果是0,其余是1(跟& 一样,就不演示)
使用场景:
对一个数据的某些位 置为1。
方法:找到一个数,对应x要置1的位,该数的对应位为1,其余位为零。
^(异或运算):当相同二进制位 ^ 运算,结果是0 , 1^1=0、0^0=0。当不同二级制位 ^ 运算,返回1, 1^0=1、 0^1=1。(异或 ---> 只有不相同时才返回1)
例:18 ^ 13
0000 0000 0000 0000 0000 0000 0001 0010
^
0000 0000 0000 0000 0000 0000 0000 1101
=
0000 0000 0000 0000 0000 0000 0001 1111
结果: 31 。
这时,一个哥哥发话了,我不....
行行行,给你看测试结果好吧!!!!!
其他: 负数 ^ 正数 、负数 ^ 负数 、正数 ^ 负数,大家举一反三的时候到了,仍然不会的可以留言呀,我倒是看看谁这么欠揍,写这么详细还不会。
使用场景:
①与1相异或,使特定位翻转
②与0相异或,保留原值
③两个变量交换值(用位异或运算来实现,也是效率最高的)
原理:一个数异或本身等于0 ;异或运算符合交换律, 如: A=A^B;B=A^B;A=A^B
~(取反) :按补码依次取反。
正数取反: ~21
原码/补码:0000 0000 0000 0000 0000 0000 0001 0101
取反: 1111 1111 1111 1111 1111 1111 1110 1010
反码: 1111 1111 1111 1111 1111 1111 1110 1001 (因为首位为1,所以计算结果前需要先算原码)
原码: 1000 0000 0000 0000 0000 0000 0001 0110
结果: -22
负数取反: ~ -21:
原码:1000 0000 0000 0000 0000 0000 0001 0101
反码:1111 1111 1111 1111 1111 1111 1110 1010
补码:1111 1111 1111 1111 1111 1111 1110 1011
取反:0000 0000 0000 0000 0000 0000 0001 0100
结果:16+4=20 。
看测试结果:
实际对 a 取反后的结果: -a-1,不用那么辛苦转码,累死累活的
三元运算符: (条件表达式) ? 表达式1 : 表达式2
如果条件表达式结果是true,则返回表达式1,条件表达式结果是false,返回表达式2
注意:
表达式1与表达式2应该为同种类型
三元运算符与if-else联系和区别:
1、三元运算符可以简化if-else语句
2、三元运算符必须返回一个结果
3,if的后边代码块可以有多个语句
例:获取两个数中较大数
能看到这里,我发现你是真的爱我,那我也想对你说一句:
把耳朵伸过来
.
.
.
.
.
.
.
如果有用,麻烦点个赞呗,软件行业的小学生,Android上的弟弟在这里跪谢了
END