5、运算符
5.1 概念
定义了指定运算规律的符号
5.2 分类
5.2.1 算数运算符
主要有:求和(+)、求差(-)、求积(*)、求商取整(/)、取余(%)、自增(++)、自减(–)。
1、运算结果的数据类型
不同类型相加减,需要进行类型间的转换;一般运算结果数据类型和元素中大的数据类型保持一致。
特殊情况:byte、short、char在参与运算时,会自动提升为int类型
例1:以byte类型为例,测试自动提升为int类型
byte b1 = 2;
byte b2 = 3;
byte sum = b1 + b2;//编译时会报错
因为byte相加的结果会自动提升为int类型的数据,而且int类型数据不能自动转换为byte类型的数据,所以byte相加的结果不能直接赋值给byte类型的sum变量。
解决方案1:将byte相加的结果强转为byte类型
byte sum =(byte)(b1+b2);
解决方案2:将byte相加的结果赋值给一个int类型的变量
int sum = b1 + b2;
例2:直接用byte类型的字面值进行求和赋值,不会报错
byte sum = 2 + 3;//不会报错
byte sum2 = 127 + 1; //编译时会报错,因为128不在byte的范围内
Java程序在编译时,存在编译优化,即对于byte字面值2+3在编译期就直接参与了运算,不会提升为int类型,优化之后的代码直接将byte类型字面值5赋值给byte类型的sum变量。但是在编译时,会检查两个字面值相加的结果是否在byte的取值范围内,若超过了范围就会报错。
例3:字符串类型可以使用 “ + ” 进行拼接
String str1 = "Hello";
String str2 = "World";
System.out.println(str1 + str2);//输出结果:HelloWorld
例4:字符串类型+基本数据类型(仅限Java中使用)
String str = "Hello";
int num = 2;
System.out.println(str1 + str2);//输出结果:HelloWorld
例5:多个表达式————按照优先级为从左到右执行(仅限Java中使用)
System.out.println("Hello" + 1 + 0.5);//输出结果:Hello10.5
System.out.println(1 + 0.5 + "Hello");//输出结果:1.5Hello
System.out.println("Hello" + 2 + 'a');//输出结果:Hello2a
System.out.println(1 + 'a' + "Hello");//输出结果:98Hello,其中'a'表示字符a,ASCII值为97
2、求商取整运算,除数为0的情况
(1)int类型
int num = 5/0;
上述代码,编译时不报错,但是运行时会出现异常(Exception in thread “main” java.lang.ArithmeticException: / by zero)
(2)浮点数
double d1 = 5.1/0;
System.out.println(d1);//输出结果:Infinity,表示无穷大
double d2 = -5.1/0;
System.out.println(d2);//输出结果:-Infinity,表示无穷小
double d3 = -0.0/0;
System.out.println(d3);//NaN————Not a Number非数字
(3)自增运算符
i++相当于 i = i +1;
i++先用后加;++i先加后用,自减同理
int i = 1;
System.out.println(i++);//输出结果:1;先将i=1输出,再对i进行自加一操作
System.out.println(i++);//输出结果:2;
int num = 1;
System.out.println(++num);//输出结果:2;先对num进行自加一操作,在将自加一结果输出
System.out.println(++num);//输出结果:3;
5.2.2 赋值运算符
1、常见的赋值运算符:
等于(=)、加等于(+=)、减等于(-=)、乘等于(*=)、取整等于(/=)、取余等于(%=)。
2、格式
变量类型 变量名 赋值运算符 常数。
int num = 1;//输出num为1
num += 2;//输出num为3,相当于num = num + 2
3、加等于的使用
(1)“加等于”支持字符串的拼接,但是只有加等于(+=)有拼接作用
String str1 = "Hello";
String str2 = "World";
str1 += str2; //相当于str1 = str1 + str2;
System.out.println(str1); //输出结果为HelloWorld
(2)“加等于”底层默认做了强制类型转换
byte b1 = 2;
byte b2 = 3;
b1 += b2; //相当于b1 = b1 + b2
//其中b1+b2的结果会自动提升为int类型,但是加等于默认将其强转为byte类型
System.out.println(b1);//输出结果:5
(3)赋值运算符的优先级是最低的
5.2.3 关系运算符
1、常见的关系运算符:
小于(<)、大于(>)、小于等于(<=)、大于等于(>=)、等于(==)、不等于(!=)
2、格式
元素 关系运算符 元素 ————二元/目运算符
3、注意
(1)运算结果为true或false,用boolean类型的变量来存储关系运算的结果;
(2)关系运算符不支持多个值进行比较,如a>b>c这种类型不符合Java语法规范
5.2.4 逻辑运算符
1、常见的逻辑运算符
与(&)、或( | )、非( ! )、异或( ^ )、双与/短路与(&&)、双或/短路或( || )
2、格式
元素 逻辑运算符 元素
3、运算结果
(1)与:全true则为true,只要有一个false则为false
(2)或:全false则为false,只要有一个true则为true
(3)非:取反,!true = false
(4)异或:相同则为false,不同则为true
(5)双与:从左向右判断,如果最左边的是false,则结束判断,不再执行后面的判断,结果直接为false;如果最左边的是true,则继续判断,若为true,则结果为true,若为false,则结果为false。
int a = 1;
System.out.println(false && a++ > 0);//false
System.out.println(a);//1
int b = 1;
System.out.println(true && b++ > 0);//true
System.out.println(b);//2
int c = 1;
System.out.println(true && c++ < 0);//false
System.out.println(c);//2
(6)双或:从左向右判断,如果最左边的是true,则结束判断,不再执行后面的判断,结果直接为true;如果最左边的是false,则继续判断,若为true,则结果为true,若为false,则结果为false。
int a = 1;
System.out.println(true || a++ > 0);//true
System.out.println(a);//1
int b = 1;
System.out.println(false || b++ > 0);//true
System.out.println(b);//2
int c = 1;
System.out.println(false || c++ < 0);//false
System.out.println(c);//2
5.2.5 三目运算符
1、格式
(布尔类型的表达式1)?表达式2 :表达式3
2、执行流程
先执行布尔类型的表达式1,若结果为true,则执行表达式2;若结果为false,则执行表达式3。
int num1 = 2;
int num2 = 3;
int max = num1 > num2 ? num1 : num2;
System.out.println(num1 + "和" + num2 + "中的较大值为" + max);//输出结果:2和3中的较大值为3
5.2.6 位运算符
1、常见位运算符
与(&)、或( | )、取反(~)、异或( ^ )、按位左移(<<)、按位右移(>>)、无符号位右移(>>>)
2、概述
主要是针对整数的二进制来做运算的,底层源码用的多,但是实际开发用的不多。
3、运算结果
(1)按位与 “&” ———— 全1则1,有0则0。
按位与 | 结果 |
---|---|
1 & 1 | 1 |
1 & 0 | 0 |
0 & 1 | 0 |
0 & 0 | 0 |
应用:
可以用于判断奇偶型————奇数&1=1,偶数&1=0
int a = 1;
int b = 2;
System.out.println( (a&1) == 1 ? "奇数" : "偶数");
System.out.println( (b&1) == 0 ? "偶数" : "奇数");
(2)按位或 “ | ” ———— 有1则1,全0才0。
按位或 | 结果 |
---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
(3)异或 “^” ————相同为0,相异为1
异或 | 结果 |
---|---|
1 ^ 1 | 0 |
1 ^ 0 | 1 |
0 ^ 1 | 1 |
0 ^ 0 | 0 |
应用:
可以利用异或进行两个数之间的交换——因为一个数异或另一个数两次,结果为该数本身。
int a = 1;
int b = 2;
a = a ^ b;
b = a ^ b;//b = a ^ b ^ b = a
a = a ^ b;//a = a ^ b ^ a = b
System.out.println("a = " + a + ",b = " + b);//a = 2,b = 1
(4)按位取反 “~” ————1取反得0,0取反得1。
计算机底层存储和计算都是基于二进制的补码。以1为例,正数的原码 = 补码,所以底层1表示为0000 0000 0000 0001,按位取反得1111 1111 1111 1110,当前得到的二进制是对1取反的补码,展现在开发工具中需要转换为原码,负数的补码 = 反码 + 1,得原码1000 0000 0000 0010,即十进制数 -2。
System.out.println(~1);//-2
System.out.println(~2);//-3
(5)有符号左移 “<<”
x<<y表示先将x转为二进制,再将x的二进制补码整体向左移y位,左移多出来的数直接舍弃,右侧空出来的位补0。
左移会使x变大:x<<y 即为x*2^y
(6)有符号右移 “>>”
x>>y表示先将x转为二进制,再将x的二进制补码整体向右移y位,右侧多出来的数直接舍弃,左侧空出来的位补和符号位一致的数(正数补0,负数补1)。
右移会使x变小:x>>y 即为x/(2^y)
(7)无符号位右移 “>>>”
x>>>y表示先将x转为二进制,将x的二进制补码整体向右移y位,右侧多出来的数直接舍弃,左侧空出来的位补0,最终无符号位右移得出来的结果均为正数。