java运算符



算术运算符

包括:+、-、*、/、%、++、–,一共七种。规则和数学中的运算规则一致。
值得注意的是除法运算符、求余运算符、自增自减运算符。

除法运算符

当/两边都是整数时,运行的是整数除法,结算的结果会忽略掉余数;而且,整数除法的除数不能为0,否则会报异常。

当/两边有一个是浮点数时,运行的是小数除法,计算结果可以有小数点,没有余数的说法;而且,小数除法的除数可以为0(0.0),除以0得到的结果为正无穷或者负无穷。

求余运算符

求余运算规则和除法运算规则类似。
当%两边都是整数时,计算结果是整数的余数;而且,如果是整数求余,除数为0也会报异常。

当%两边有一个是浮点数时,计算结果是带小数点的余数,也就是整除完剩下的部分;如果是小数求余,当除数为0(0.0)时,会得到非数NaN;0(0.0)对零以外的任何数求余,都会得到零。

自增自减运算符

自增运算符是单目运算符,只能操作单个数值型变量,不能操作常量或表达式。
++如果在操作数左边,要先把操作数+1,再将操作数放入表达式计算。
++如果在操作数右边,要将操作数放入表达式计算,再把操作数+1。

自减运算符的规则同理。

乘方、开方等操作

java没有提供更多的算术运算符。如果要完成更复杂的算术运算,需要借助Math类的方法。
乘方:Math.pow(x,y); 含义是 x y x^{y} xy
平方根:Math.sqrt(x); 含义是x的平方根
计算随机数:Math.random(); 返回[0,1)的伪随机数



位运算符

java支持7种位运算符,分别是:&、|、~、^、<<、>>、>>>

按位与、或、非、和异或

先介绍前面4种:
按位与、或、非、异或。
这几种运算符的操作数都是整型的变量或者值,它们都是将整型的值按位进行计算,再组合成最终结果。
&:按位与。当两位同时为1时才返回1。
|:按位或。只要有一位为1就返回1。
~:按位非。单目运算符,将单个操作数的每一位(包括符号位)全部取反。
^:按位异或。当两位相同时返回0,不相同就返回1。
再次注意:计算是按位计算,分别得到每一位的结果后,再组合成最终结果
举例:
在这里插入图片描述
这4个运算符不仅仅可以做按位运算,如果运算符两边是布尔类型的操作数,那它们就变成逻辑运算符,后面的小节会介绍
也就是说,这4个运算符的含义,会根据上下文的含义改变。

按位异或的特殊用法

int x = 5;
int y = 7;
x = x^y;
y = y^x;	// 结合上一行,相当于y = y^(x^y) = y^y^x = x,所以这样就让y的值变成了x
x = x^y;    // 结合上面两行,相当于x = (x^y)^x = x^x^y = y,所以,这样就让x的值变成了y

所以,异或运算可以实现不借助第三个变量交换两个变量的值。这种运算效率应该是相当高的。

移位运算符

移位运算符不会改变操作数本身,而是将左边的操作数移动(左移或者右移)右边指定的位数

移位运算符规则

<<:左移运算符
左移运算符是将左边操作数的二进制补码整体左移右边操作数指定的位数,比如a << b就相当于把操作数a左移b位。左移后右边空出来的位以0填充左边移出去的位直接截断

举例:

	System.out.println(-5 << 2); // 结果为-20

图解如下:
在这里插入图片描述
可以看出来,左移后,只要没发生有效位的丢失。比如负数左移截断的全是1,正数左移截断的全是0。那左移n位,就相当于操作数乘以2的n次方

>>:右移运算符
右移运算符是将左边操作数的二进制补码整体右移右边操作数指定的位数,比如a >> b就相当于把操作数a右移b位。右移后左边空出来的位根据原来操作数的符号位填充如果左边操作数a是正数,则填充0;如果左边操作数a是负数,则填充1

举例:

	System.out.println(-5 >> 2); // 结果为-2
	System.out.println(5 >> 2); // 结果为1

图解如下:
在这里插入图片描述
>>>:无符号右移运算符
无符号右移运算符和右移运算符的唯一区别是,左边空出来的位数全部填充0。
所以,如果左边的操作数a是正数,那么无符号右移运算和右移运算没有任何区别。
但是,如果左边的操作数a是负数,那么无符号右移填充的符号位是0,会把负数变成正数。

	System.out.println(5 >>> 2); // 结果和5>>2没任何区别,为1
	System.out.println(-5 >>> 2); // 结果为1073741822,因为左边填充的是0,所以变成了很大的正数

可以看出来,有符号的右移,只要没发生有效位的丢失。那右移n位,就相当于操作数除以2的n次方而无符号的右移,只要左边操作数为负,就会变成正数,结果是不可预测的

移位运算符根据操作数类型的规则

1.如果左边操作数低于int类型(byte、short、char),那么操作数总是先自动转换为int类型后再移位。
2.int类型的整数移位a>>b,如果b>=32,那么需要先用b对32求余。比如a>>33 等价于 a>>1。
3.long类型的整数移位a>>b,如果b>=64,那么需要先用b对64求余。比如b>>64等价于b本身。



赋值运算符

赋值运算符会把等号右边的值赋值给等号左边的变量。
比如:int a = 3;
赋值表达式的值就是右边被赋的值。
所以,赋值运算符支持连续赋值(但是为了可读性不推荐这样做)。
比如 int x = y = z = 5; // z = 5这个表达式的值就是5,所以y = 5,而y = 5这个表达式的值也为5,所以x = 5

扩展后的赋值运算符

赋值运算符可与算术运算符位移运算符结合。
比如:
+=、-=、*=、<<=、>>>=、^=、|=等等。
这种写法都是固定的含义:比如 x >>= a; 等价于 x = x >> a;
写程序非常推荐这种写法,第一是简洁,第二是健壮性更好。
这种写法可以避免一个隐晦的错误。

	byte a = 4;
	// 下面这行会报错,因为右边表达式为int类型,赋值给左边byte类型变量需要强制类型转换
	a = a + 4; 
	// 但是用扩展后的赋值运算符就没问题
	a += 4;		// 说明这两种写法的底层实现不一样,了解就行


比较运算符

比较运算符用于判断两个值的大小。
比较运算符对应的表达式的计算结果为布尔值(true或false)。

比较运算符就如下这些:
>、>=、<、<=、==、!=
前面4个的计算方式和数学中的方式差不多,左右操作数只支持数值类型

等于运算符

==等于运算符左右的操作数可以是数值类型,也可以是引用类型

1.对于数值类型:即使左右操作数数据类型不相同,只要它们的值相等,也都将返回true。
比如3.0 == 3, 97== ‘a’。
比较特殊的是,布尔类型只能和布尔类型比较(因为只有这种数值类型代表正假)。

2.对于引用类型只有两个引用变量类型相同或者具有父子关系时,才可以比较,必须两个引用指向他同一个对象才会返回true
引用类型不能和数值类型比较

不等于运算符

!=:不等于运算符左右的操作数可以是数值类型,也可以是引用类型。

1.对于数值类型:数值类型之间进行比较,只要值不相等,就返回true,不需要管左右操作数是什么类型。
布尔类型只能和布尔类型比较

2.对于引用类型:只有当两个引用变量的类型具有父子关系或者类型相同时,才可以比较(因为这才有比较的价值)。只要两个引用不指向同一个对象,就返回true
引用类型不能和数值类型比较



逻辑运算符

逻辑运算符的两个操作数是布尔类型的值,经常左右两边都是布尔类型的表达式。
逻辑运算符有6个:&&、&、||、|、!、^这6个

注意:其实&、|、!、^这4个符号,当左右操作数是整数类型的值,就变成了位运算符,前面已经讲过了。

这些运算符的计算方式都很简单。和数学的代数中的计算方式完全一致。

比较值得提的是不短路与(或)和短路与(或)。

短路与(或)和不短路与(或)

短路的写2个符号:&& 和 ||
不短路的写一个符号:& 和 |
和物理中的短路含义差不多,短路的意思是,如果已经可以确切知道结果,那么就不计算第二个操作数的布尔值。
比如: 3 < 5 || b++ == 10;
因为第一个表达式已经为真,所以整个逻辑或的表达式的值为真,所以第二个表达式就不执行。
所以,变量b的值不会加一。
与之对比:3 < 5 | b++ ==10; 因为是不短路或,所以无论如何,第二个表达式的值都要计算,所以变量b的值会加1。



三目运算符

三目运算符和if else的作用差不多。
语法格式为:(expression) ? statement1 : statement2;
如果逻辑表达式为真,就执行statement1,否则执行statement2。

一般,如果需要写if else,而且每个分支的执行语句就一句的时候,就可以考虑用三目运算符。它就相当于if else的简写方法。

嵌套三目运算符

这种方式其实不太推荐使用。
因为三目运算符后面2个表达式只能写一个语句,为了增强功能,就可以试用嵌套的三目运算符。
比如:(expression) ? ((expression) ? statement1 : statement2) : statement3;
相当于把其中一个分支改成了一个三目运算符的表达式。
等价于if else 的嵌套。
上面相当于,if成立时的分支内部嵌套了一个if else语句。



运算符的优先级和结合性

优先级:不同运算符的优先级是不一样的。
抽象出格式:表达式1 操作符1 表达式2 操作符2 表达式3;
这时候,表达式2被夹在了操作符1和操作符2之间,到底先计算哪个,是由优先级决定的。
作为java程序员,程序的可读性更重要,如果搞不清楚优先级就直接打上括号。一般情况下,优先级都是按照你最舒服的方式规定的,没必要去死背。

结合性:绝大部分的运算符的结合性都是从左到右结合的,只有单目运算符(++和–和~和!)赋值运算符三目运算符从右向左结合的。
抽象出格式:表达式1 操作符1 表达式2 操作符2 表达式3;
结合性往往是两个操作符的优先级一样时,才会起作用
假如操作符1和操作符2的优先级一致,表达式2被夹在中间,到底是先算哪个操作符就看操作符的结合性。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值