java运算符

java运算符

运算:对常量和变量进行操作的过程称为运算。
运算符:对常量和变量进行操作的符号称为运算符,用来指明对操作数采取什么运算方式的一种符号。
操作数:参与运算的数据称为操作数。
表达式:用运算符把常量或者变量连接起来的符合Java语法的式子称为表达式。不同运算符连接的式子体现的是不同类型的表达式。

  • java按操作个数可分为:单目运算符、双目运算符、三目运算符,有几个操作数参与运算就是几目运算符
  • Java运算符按功能可分为:算术运算符、赋值运算符、关系运算符、逻辑运算符、位运算符和条件运算符等。

按操作数划分

类型符号
单目运算符~(按位取反)、! (取非)、-(负号运算符)、 ++(自增)、 - -(自减)
双目运算符+ - * /%(取余)
三目运算符? :

按功能划分

算术运算符

操作符描述例子
+加法 : 相加运算符两侧的值int A=20;int B=10;A + B 等于 30
-减法 : 左操作数减去右操作数int A=20;int B=10; A – B 等于 10
*乘法 : 相乘操作符两侧的值int A=20;int B=10;A * B等于200
/除法 : 左操作数除以右操作数int A=20;int B=10;B / A等于0
取余 : 左操作数除以右操作数的余数int A=20;int B=10;B%A等于10
++自增: 操作数的值增加1int A=20;int B=10;B++ 或 ++B 等于 11
自减: 操作数的值减少1int A=20;int B=10;B-- 或 --B 等于 9

在算术表达式中包含多个基本数据类型的时候,整个算术表达式会进行自动类型提升
提升规则:

  • 整数类型操作数进行运算的时候,默认提升到int类型
  • 整个表达式中的类型自动提升到表达式中最高等级操作数同样的类型
    提升顺序:

在这里插入图片描述
注意:

在加号遇到双引号之前,都只做加法运算,遇到双引号之后所有的加号都是连接符,除非在双引号的后面加上小括号

  • +操作中出现字符串时,这个+是字符串连接符,而不是算术运算符。
    如:1 + "1" + 1 == 111
  • +操作中,如果出现了字符串,就是连接运算符,否则就是算术运算。当连续进行+操作时,从左到右逐个执行。
    如:1+1+"1" == 21
  • 在双引号的后面加上小括号,可以进行算术运算
    如:1+”1”+(1+1+1)---->113
  • Java中的boolean不能参与算数运算。
自增自减
  • 自增自减符在操作数之后:a++,则先拿操作数进行运算,最后再把操作数加一
  • 自增自减符在操作数之前:++a,则先把操作数加一,最后再拿操作数进行运算
  • 单独使用时,无论放在前面还是后面,结果都相同

运算:
将变量空间的内容先取出来,与常量区取出来的值进行计算,最后再把结果放回内存空间,而变量空间的内容要做值交换(值计算、运算)时,会先创建一个临时的副本空间(备份空间),把变量空间的内容备份过去,++在前则先进行计算再备份,++在后则先进行备份,再进行计算,然后把备份的内容赋给别人,如果赋给自己,则前面的内容会被副本空间的内容覆盖,运算结束副本空间会被清除
在这里插入图片描述

在这里插入图片描述

所有参与运算的变量都会先将变量空间的值备份在计算

赋值运算符

赋值运算符就是把赋值符右边的内容赋给左边的变量空间

运算符作用说明
=赋值a=10,将10赋值给变量a
+=加后赋值a+=b,将a+b的值给a
- =减后赋值a-=b,将a-b的值给a
* =乘后赋值a*=b,将axb的值给a
/ =除后赋值a/=b,将a÷b的商给a
% =取余后赋值a%=b,将a÷b的余数给a

i += 20与i = i + 20运算结果一样,但是过程不同

// 扩展的赋值运算符底层隐含了强制类型转换
short s = 10;
s += 20; // 等价于 s = (short)(s + 20);
System.out.println("s: " = s); // s = 30

short s1 = 10;
s1 = (short)(s1 + 20);
System.out.println("s1: " = s1); // s = 30
// Error: java: 不兼容的类型: 从int转换到short可能会有损失
short s2 = 10;
s2 = s2 + 20;
System.out.println("s2: " = s2); // 报错

由于整数参与运算默认为int类型,直接拿两个int类型的数进行操作,得到的结果为int类型,所以报精度损失错误。
为什么扩展的赋值运算符不报错?
因为扩展的赋值运算符底层隐含了强制类型转换,即默认进行强制类型转换,所以不会报错

关系运算符

运算符描述例子
==检查如果两个操作数的值是否相等,如果相等则条件为真。(A == B)为假。
!=检查如果两个操作数的值是否相等,如果值不相等则条件为真。(A != B) 为真。
>检查左操作数的值是否大于右操作数的值,如果是那么条件为真。(A> B)为假。
<检查左操作数的值是否小于右操作数的值,如果是那么条件为真。(A <B)为真。
>=检查左操作数的值是否大于或等于右操作数的值,如果是那么条件为真。(A> = B)为假。
<=检查左操作数的值是否小于或等于右操作数的值,如果是那么条件为真(A <= B)为真。
public class Test {
 
  public static void main(String[] args) {
     int a = 30;
     int b = 20;
     System.out.println("a == b = " + (a == b) ); // false
     System.out.println("a != b = " + (a != b) ); // true
     System.out.println("a > b = " + (a > b) ); // true
     System.out.println("a < b = " + (a < b) ); // false
     System.out.println("b >= a = " + (b >= a) ); // false
     System.out.println("b <= a = " + (b <= a) ); // true
  }
}

逻辑运算符

运算符名称描述
&逻辑与符号两边都为真,则条件为真
|逻辑或符号两边都为假,则条件为假
!逻辑非对符号右边的值取反
^逻辑异或只有两个判定条件相反,则条件为真
&&短路与作用和逻辑与相同,但是具有短路效果
||短路或作用和逻辑或相同,但是具有短路效果
public class Test {
  public static void main(String[] args) {
     boolean a = true;
     boolean b = false;
	 System.out.println("a & b = " + (a&b)); // a & b = false
     System.out.println("a | b = " + (a|b) ); // a | b = true
	 System.out.println("!a = " + !a); // !a = false
     System.out.println("a ^ b = " + (a ^ b)); // a ^ b = false
     System.out.println("a && b = " + (a&&b)); // a && b = false
     System.out.println("a || b = " + (a||b) ); // a || b = true
  }
}

注意事项:

  • 逻辑与&,无论左边真假,右边都要执行
    短路与&&,左边为真,执行右边;左边为假,右边不执行
  • 逻辑或| ,无论左边真假,右边都要执行
    短路或||,左边为假,执行右边;左边为真,右边不执行
public class Test {
  public static void main(String[] args) {
	 // 测试逻辑与和短路与在两边分别为真、假时的结果
	 int a = 5;
	 int b = 5;
	 int a1 = 5;
	 int b1 = 5;
     boolean c = (a<4)&&(a++<10);
	 boolean d = (b>4)&&(b++<10);
	 boolean c1 = (a1<4)&(a1++<10);
	 boolean d1 = (b1>4)&(b1++<10);
     System.out.println("短路与&&,左边为假时:"+c+",a = "+a);
     System.out.println("逻辑与& ,左边为假时:"+c1+",a1 = "+a1);
	 System.out.println("短路与&&,左边为真时:"+d+",b = "+b);
     System.out.println("逻辑与& ,左边为真时:"+d1+",b1 = "+b1);
	 System.out.println();
	 // 测试逻辑或和短路或在两边分别为真、假时的结果
	 int e = 5;
	 int f = 5;
	 int e1 = 5;
	 int f1 = 5;
     boolean g = (e<4)||(e++<10);
	 boolean h = (f>4)||(f++<10);
	 boolean g1 = (e1<4)|(e1++<10);
	 boolean h1 = (f1>4)|(f1++<10);
	 System.out.println("短路或||,左边为假时:"+g+",e = "+e);
     System.out.println("逻辑或| ,左边为假时:"+g1+",e1 = "+e1);
	 System.out.println("短路或||,左边为真时:"+h+",f = "+f);
     System.out.println("逻辑或| ,左边为真时:"+h1+",f1 = "+f1);
  }
}

结果为:

短路与&&,左边为假时:false,a = 5
逻辑与& ,左边为假时:false,a1 = 6
短路与&&,左边为真时:true,b = 6
逻辑与& ,左边为真时:true,b1 = 6

短路或||,左边为假时:true,e = 6
逻辑或| ,左边为假时:true,e1 = 6
短路或||,左边为真时:true,f = 5
逻辑或| ,左边为真时:true,f1 = 6

位运算符

运算符名称描述
&按位与两个操作数按照二进制对比,同位对应二进制数都是1,则结果是1
|按位或两个操作数按照二进制对比,同位对应二进制数都是0,则结果是0
~按位取反(按位非)把该操作数的二进制数取反值(值加一取反:~5==5+1==6取反得 -6)
^按位异或两个操作数按照二进制对比,同位对应二进制数相同时,则结果是0
<<左移按二进制形式把所有的数字向左移动N位,高位移出(舍弃),低位补零
>>右移按二进制形式把所有的数字向右移动N位,低位移出(舍弃),正数高位补零,负数补1
>>>无符号右移(逻辑右移)按二进制形式把所有的数字向右移动N位,低位移出(舍弃),高位补零
注意事项:
	要做位运算,首先要把数据转换为二进制的补码。
	按位异或的特点:一个数据对另一个数据按位异或两次,该数本身不变。
	乘法运算在计算机内可以左移运算来实现。
	在Java中进行位移运算时,移动的位数只取二进制补码后面的五位。
有符号数据的表示法:
    在计算机内,有符号数据有三种表示法:原码、反码和补码。计算机中数据的储存和运算都是采用数据对应的二进制的补码来进行的。
    (1)原码
	就是二进制的定点表示法,即最高位为符号位,“0”表示正,“1”表示负,其余位表示数值的大小。
    (2)反码
	正数的反码与其原码相同,负数的反码是对其原码逐位取反,但符号位除外。
    (3)补码
	正数的补码与其原码相同,负数的补码是在其反码的末位上加1。

原码、补码、反码 视频链接
在这里插入图片描述

&: 两个操作数按照二进制对比,同位对应二进制数都是1,则结果是1
		 3 & 5==1
		 3   00000000 00000000 00000000 00000011
		 &
		 5   00000000 00000000 00000000 00000101
		 =   00000000 00000000 00000000 00000001
|:两个操作数按照二进制对比,同位对应二进制数都是0,则结果是0
^:两个操作数按照二进制对比,同位对应二进制数相同时,则结果是0
		 2 ^ 3==1
		 2   00000000 00000000 00000000 00000010
		 ^   
		 3   00000000 00000000 00000000 00000011
		 =   00000000 00000000 00000000 00000001
						
~:把该操作数的二进制数取反值(口诀:值加一取反:~ 5 = 5 + 1 = 6取反得 -6)
计算机中的数字都是以补码的形式进行存储和运算,以原码的形式展示的
正数的补码、反码与原码一致,负数的反码 = 符号位不变,原码取反  负数的补码 = 反码 + 1,
补码、原码、反码都是一种表现形式,按位取反是一个计算过程(每个位置都取反)

反    码:最高位符号位不变,然后依次取反
按位取反:所有位都取反,即符号位也取反

由于正数的原码、反码、补码都相同,且计算过程都使用补码计算,所以:
5的原码       00000000 00000000 00000000 00000101
5的补码       00000000 00000000 00000000 00000101
按位取反      ~
计算结果		 11111111 11111111 11111111 11111010
当前的计算结果是补码的形式,可以看出这是一个负数,要展示时使用原码,所以要先求反码。
而负数的反码 = 负数的补码 - 1
负数反码 	 11111111 11111111 11111111 11111001
由于结果都使用原码展示,所以要求该结果的原码。负数的原码 = 反码的符号位不变,其余取反
负数原码   	 10000000 00000000 00000000 00000110 = -6
即:
	 ~ 5 = ~ 00000000 00000000 00000000 00000101
		   = 11111111 11111111 11111111 11111010
	反码	 	 11111111 11111111 11111111 11111001
	原码		 10000000 00000000 00000000 00000110 = -6
	所以:~5 = -6
	
<<:把一个数左移N为,右边空位补充0
		2<<2 = 8
		1    00000000 00000000 00000000 00000010
左移两位	1向左移动2个位置
		   = 00000000 00000000 00000000 00001000

按位取反快速计算口诀:值加一取反

在做左位移、右位移运算时,原值不变,会重新分配一个内存空间储存位移运算之后的值。有符号右移时,最高位是零就在左边补零,最高位是1就在左边补1,即有符号右移运算不会改变正负值;无符号右移时,在最左边补零,即正数不变,负数变为正数。

 public static void main(String []args) {
		int i = - 8;
		System.out.println(i); // 输出 -8
		int j = i >> 2;
        System.out.println(i); // 输出 -8
		System.out.println(j); // 输出 -2
		int k= i >>> 2;
		System.out.println(k); // 输出 1073741822,正负值被改变
    }

条件运算符 ? :

格式: 关系表达式?表达式1:表达式2

三目运算符(条件运算符):
格式:(关系表达式)?表达式1:表达式2;
	    如果条件为true,运算后的结果是表达式1;
	    如果条件为false,运算后的结果是表达式2。
三目运算符(条件运算符)是一个整体,即如果三目运算符中有double类型,结果也将提升到double
如:true12.0//结果为1.0

计算规则:

首先计算关系表达式的值

  • 如果值为true,表达式1的值就是运算结果
  • 如果值为false表达式2的值就是运算结果
public class Test {
  public static void main(String[] args) {
	 int a = 5;
	 int b = 6;
	 int c = a > b ? a : b; 
	 System.out.println("c = " + c); // c = 6
  }
}

& 与&&的异同:

相同点:都是两个true结果就为true
区别:
(1)&可以是逻辑运算符也可以是位运算符,&&只能是逻辑运算符
(2)如果都是逻辑运算符时:无论第一个结果是不是true,&都要继续判断下一个条件,而&&只要第一个不为true,则发生短路,不再继续判断后面的条件,输出结果为false,只要第一个判断条件为false,&&&更高效
(3)当&中参与运算的两边是整数时默认执行的是位运算,而两边是boolean值时执行的是逻辑运算,

| 与||的异同:

相同点:只要一个结果为true结果就为true
区别:
(1)|可以是逻辑运算符也可以是位运算符,||只能是逻辑运算符
(2)如果都是逻辑运算符时:无论第一个结果是不是true,|都要继续判断下一个条件,而||只要第一个为true,则发生短路,不再继续判断后面的条件,输出结果为true,只要第一个判断条件为true,|||更高效
(3)当|中参与运算的两边是整数时默认执行的是位运算,而两边是boolean值时执行的是逻辑运算,

两个变量值的交换方式

int a = 1; int b = 2;1)第一种方式:
int c = a;    a = b;   b = c;//利用第三方空间进行交换
优点:容易理解,值不会出现问题    
缺点:要定义一个第三方空间,造成内存空间的浪费

(2)第二种方式:(效率较高)
a = a + b;  b = a - b;  a = a - b;
优点:不用定义第三方空间,不会造成空间浪费   
缺点:可能发生值越界,不易理解

(3)第三种方式:(效率较高,且较安全)
a = a ^ b;  b = a ^ b;  a = a ^ b;
原理:一个数异或同一个数两次,值不会发生改变
优点:不用定义第三方空间,不会造成空间浪费,且不易造成值越界   
缺点:不易理解

怎么最有效率的计算3*8?

3<<3==24效率最高(8==2的3次幂)
当一个数是2的次幂时,用位移运算效率更高

左位移几位,就是乘以2的几次方,右位移几位就是除以2的几次方
如:3<<3:3向左位移3,就是3乘以(8)2的3次方等于24
10>>1:10向右位移1位,10除以2的1次方等于5

基本数据类型五条运算规则:

①计算结果的数据类型,与表达式中最大或最精确的类型一致
②byte、short、char参与运算时,将先自动转为int类型
byte a = 1, b = 2; byte c = a + b;//结果错误,因为右边表达式为 int +int ,左边为byte
③整数运算溢出
Integer.MAX_VALUE + 1 将变为负数最小值
运算就像时钟转圈,从最小到最大,然后直接到最小,如1点到12点,再走又回到1点
④浮点数运算不精确,可以用BigDecimal类计算精确值
2 - 1.9 = 0.1000000000009
⑤浮点数的特殊值
Infinity -------- 无穷大 由浮点数除以0 得到
NaN ---------- 不是数 由负数开平方得到

基本类型的5条字面值规则:

①整数的字面值为int类型,即整数默认为int类型
long a = 9999999999;//编译报错,虽然a是long类型变量,但是9999999999默认是int类型数据,超出int范围
正确声明方式为:long a = 9999999999L;//要在字面值后面加上L ,显式的标明9999999999是long类型
②byte、short、char在规定范围内可以直接赋值,当超出自身范围时,将自动变为int类型
byte a = 127;///结果为byte类型
byte a = 128;//由于128超出了byte类型范围,自动转换为ing类型,所以会编译报错
③浮点数字面值为double类型
④字面值后缀:
L ---- long
F ---- float
D ---- double
​⑤进制前缀
0x ----- 16进制 0xff = 255
0 ----- 8进制 0377 = 255
\u ----- char类型16进制 ‘\u0061’ =》 二进制:0000 0000 0110 0001 =》十进制:97=》char类型:a
注意:cahe类型16进制必须完整表示,即\u后面必须跟4个数字

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值