运算符
Java语言支持的运算符:
- 算术运算符:+, -, *, /, %, ++, –
- 赋值运算符:=
- 关系运算符:>, <, >=, <=, ==, !=, instanceof(面向对象会学到)
- 逻辑运算符:&&, ||, !
- 位运算符:&, |, ^, ~, >>, <<, >>>
- 条件运算符:? : (又叫三目运算符)
- 扩展赋值运算符:+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, >>>=
基本运算符
算术运算符(+, -, *, /, %)
- 对应数学中加,减,乘,除,取余(java中称为模运算)
public class ArithmeticOperator {
public static void main(String[] args) {
System.out.println("===================算术运算符===================");
// 算术运算符:+, -, *, /, %, ++, --
// 对应数学中加,减,乘,除,取余(java中称为模运算)
// Ctrl + D :复制当前行到下一行 (IDEA快捷键)
System.out.println("---------加,减,乘,除(二元运算符)---------");
int a = 1;
int b = 2;
int c = 3;
int d = 4;
System.out.println(a + b); // 输出值3
System.out.println(a - b); // 输出值-1
System.out.println(a * c); // 输出值3
System.out.println(a / c); // 输出值0,整型相除只能得到整数,不会出现小数,需要进行强转
System.out.println(a / (double) c); // 输出值0.3333333333333333
System.out.println();
long l = 12345678456L;
int i = 100;
short s = 10;
byte by = 8;
// 当运算中有不同数据类型参与计算时,计算结果都会转化为高容量数据类型
System.out.println(l + i + s + by); // 输出值12345678574
System.out.println(i + s + by); // 输出值118
System.out.println(s + by); // 输出值18
System.out.println();
System.out.println("---------取余(java中称为模运算)(二元运算符)---------");
int a1 = 1;
int a2 = 2;
System.out.println(a1 % a2); // 输出值1,1除以2,余数为1
System.out.println();
}
}
算术运算符(++, --)
- ++ 符号:自增 int c = ++a 先执行a=a+1加法在赋值给c,int c = a++ 先将a赋值给c,再执行a=a+1加法
- – 符号:自减 int c = --a 先执行a=a-1减法在赋值给c,int c = a-- 先将a赋值给c,再执行a=a-1减法
- ++和–在变量前则先运算,再赋值
- ++和–在变量后则先赋值,再运算
public class IncrementDecrementOperator {
public static void main(String[] args) {
System.out.println("===================自增,自减(一元运算符)===================");
// ++ 符号:自增
// int c = ++a 先执行a=a+1加法在赋值给c,int c = a++ 先将a赋值给c,再执行a=a+1加法
// -- 符号:自减
// int c = --a 先执行a=a-1减法在赋值给c,int c = a-- 先将a赋值给c,再执行a=a-1减法
// ++和--在变量前则先运算,再赋值
// ++和--在变量后则先赋值,再运算
int a3 = 10;
int a4 = a3++; // a3 = a3 + 1
int a5 = ++a3;
System.out.println(a3); // 输出值12
System.out.println(a4); // 输出值10
System.out.println(a5); // 输出值12
System.out.println();
int a6 = 10;
int a7 = a6++; // a6 = a6 + 1
System.out.println(a6); // 输出值11
int a8 = ++a6;
System.out.println(a6); // 输出值12
System.out.println(a7); // 输出值10
System.out.println(a8); // 输出值12
System.out.println();
}
}
赋值运算符(=)
- 赋值运算符在Java中经常会被使用到:int A = 10,意思为将10赋值给A变量
public class AssignmentOperator {
public static void main(String[] args) {
System.out.println("===================赋值运算符===================");
// 赋值运算符:=
// 赋值运算符在Java中经常会被使用到:int A = 10,意思为将10赋值给A
int ai = 100;
System.out.println(ai);
System.out.println();
}
}
关系运算符(>, <, >=, <=, ==, !=)
- 对应数学中大于,小于,大于等于,小于等于,等于(Java中等于为两个 == 进行表示),不等于
- 关系运算符运算结果是布尔型,布尔型值(boolean)只有正确(true)或错误(false)
public class RelationalOperator {
public static void main(String[] args) {
System.out.println("===================关系运算符===================");
// 关系运算符:>, <, >=, <=, ==, !=, instanceof
// 对应数学中大于,小于,大于等于,小于等于,等于(Java中等于为两个 == 进行表示),不等于
// 关系运算符运算结果是布尔型,布尔型值(boolean)只有正确(true)或错误(false)
int a = 1;
int b = 2;
System.out.println(a > b); // 输出值false
System.out.println(a < b); // 输出值true
System.out.println(a == b); // 输出值false
System.out.println(a != b); // 输出值true
System.out.println();
}
}
逻辑运算符(&&, ||, !)
- 逻辑运算符对应数学中的与(and),或(or),非(取反)
- && 与运算:两个变量为真,结果为true
- || 或运算:两个变量有一个为真,结果为true
- ! 取反运算:如果结果为真true,取反结果为假false
public class LogicalOperator {
public static void main(String[] args) {
System.out.println("===================逻辑运算符===================");
// 逻辑运算符:&&, ||, !
// 逻辑运算符对应数学中的与(and),或(or),非(取反)
// && 与运算:两个变量为真,结果为true
// || 或运算:两个变量有一个为真,结果为true
// ! 取反运算:如果结果为真true,取反结果为假false
boolean a = true;
boolean b = false;
//
System.out.println("a && b:" + (a && b));
System.out.println("a || b:" + (a || b));
System.out.println("!(a && b):" + !(a && b));
// 短路运算
int c = 5;
boolean d = (c < 4) && (c++ < 4); // 因为(c < 4)不为真,所以后面的(c++ < 4)不会再执行
System.out.println(d);
System.out.println(c);
}
}
字符串连接符(+)
public class StringConcateNation {
public static void main(String[] args) {
System.out.println("=================== 字符串连接符 ===================");
// "a && b:" + 此处表达式中的加号为字符串连接符
int c = 5;
System.out.println(c); // 输出值5
System.out.println(2+c); // 输出值7
System.out.println(""+2+c); // 输出值25,字符串在前,直接进行数据拼接
System.out.println(2+c+""); // 输出值7,字符串在后,数值先进行相加,再进行字符串拼接
}
}
扩展运算符
位运算符(&, |, ^, ~, >>, <<, >>>)
- 二进制进行位运算需要将其转化为补码形式在进行运算,正数的反码和补码与原码相同,负数有所不同,负数高位不变,其他位取反,得到反码,再反码的基础上 +1 就可以得到其补码
- 计算机的字长总是8的整数倍,最小是8位,以8位为例,最高位代表了数值的正负号,0代表为正数,1代表是负数
- 此处以8字长进行举例,计算机在进行运算时,都会将他们转化为补码进行运算
- 正数的反码和补码依然是其本身,负数反码是原码高位不变,其他位取反,得到反码,反码基础上 +1 得到补码
- 8 = 二进制 [0000 1000]原码 = 二进制[0000 1000]反码 = 二进制[0000 1000]补码
- -9 = 二进制[1000 1001]原码 = 二进制[1111 0110]反码 = 二进制[1111 0111]补码
- 位运算符处理的是二进制计算,按每一位的数值进行比较
- & 按位与运算 将参与运算的两个值转换为二进制按位进行 ‘与’ 运算操作,遵循 “一假则假” 的原则(&&对两个布尔值操作)
- | 按位或运算 将参与运算的两个值转换为二进制按位进行 ‘或’ 运算操作,遵循 “一真则真” 的原则
- ^ 按位异或运算 将参与运算的两个值转换为二进制按位进行 ‘异或’ 运算操作,遵循 “两真为假,两假为假,一假一真为真” 的原则
- ~ 按位取反运算(按位非) 将参与运算的一个值转换为二进制按位进行 ‘取反’ 运算操作,取反操作属于一元运算,当二进制位数值为 0 时,取反后为 1 ;当二进制位数值为 1 时,取反后为 0
- << 左移运算 含义相当于十进制 ×2 例子:1 << 2 等同于 1 × 2 × 2,公式 m << n = m × 2^n,m 为所有正负数,0除外,且n >= 0 ,因为n < 0时结果为0,m << n 将m的二进制数(Java中的补码表示)左移 n 位,右边补0;>>右移运算 含义相当于十进制 ÷2 例子:4 >> 2 等同于 4 ÷ 2 ÷ 2,公式 m << n = m × 0.5^n,m 为所有正负数,0除外,且n >= 0 ,因为n < 0时结果为0,m >> n 将m的二进制数(Java中的补码表示)右移 n 位,正数右移,高位用0补,负数右移,高位用1补;>>> (无符号右移)与 >> 右移运算区别便是没有符号,无符号右移则不论正负高位全部补0
public class BitOperator {
public static void main(String[] args) {
System.out.println("===================位运算符===================");
// 位运算符:&, |, ^, ~, >>, <<, >>>
// 位运算符处理的是二进制计算,按每一位的数值进行比较
/*
* 二进制
* 0000 0000 0
* 0000 0001 1
* 0000 0010 2
* 0000 0011 3
* 0000 0100 4
* 0000 0101 5
* 0000 0110 6
* 0000 0111 7
* 0000 1000 8
* 0001 0000 16
*/
// 在java中int型占用4个字节,一个字节对应8位,也就是int型是32位,自己为了方便看,用8位进行表示
// 60 = 二进制 [0011 1100]原码 = 二进制[0011 1100]反码 = 二进制[0011 1100]补码
// 13 = 二进制 [0000 1101]原码 = 二进制[0000 1101]反码 = 二进制[0000 1101]补码
int a = 60;
int b = 13;
// -60 = 二进制 [1011 1100]原码 = 二进制[1100 0011]反码 = 二进制[1100 0100]补码
// 13 = 二进制 [0000 1101]原码 = 二进制[0000 1101]反码 = 二进制[0000 1101]补码
int c = -60;
int d = 13;
System.out.println("------------------- & 按位与运算 -------------------");
// & 将参与运算的两个值转换为二进制按位进行 ‘与’ 运算操作
// 遵循 “一假则假” 的原则(&&对两个布尔值操作)
// 从右往左依次按位进行比较
// 60 = 二进制[0011 1100]补码
// 13 = 二进制[0000 1101]补码
// ------ & 按位与运算 ------
// = 二进制[0000 1100]补码
// = 十进制[12]
System.out.println(a & b); // 输出值12
// 从右往左依次按位进行比较
// -60 = 二进制[1100 0100]补码
// 13 = 二进制[0000 1101]补码
// ------ & 按位与运算 ------
// = 二进制[0000 0100]补码
// = 十进制[4]
System.out.println(c & d); // 输出值4
System.out.println("------------------- | 按位或运算 -------------------");
// | 将参与运算的两个值转换为二进制按位进行 ‘或’ 运算操作
// 遵循 “一真则真” 的原则
// 从右往左依次按位进行比较
// 60 = 二进制[0011 1100]补码
// 13 = 二进制[0000 1101]补码
// ------ | 按位或运算 ------
// = 二进制[0011 1101]补码
// = 十进制[61]
System.out.println(a | b); // 输出值61
// 从右往左依次按位进行比较
// -60 = 二进制[1100 0100]补码
// 13 = 二进制[0000 1101]补码
// ------ | 按位或运算 ------
// = 二进制[1100 1101]补码 逆推原码
// = 二进制[1100 1100]反码
// = 二进制[1011 0011]原码
// = 十进制[-51]
System.out.println(c | d); // 输出值-51
System.out.println("------------------- ^ 按位异或运算 -------------------");
// ^ 将参与运算的两个值转换为二进制按位进行 ‘异或’ 运算操作
// 遵循 “两真为假,两假为假,一假一真为真” 的原则
// 从右往左依次按位进行比较
// 60 = 二进制[0011 1100]补码
// 13 = 二进制[0000 1101]补码
// ------ ^ 按位异或运算 ------
// = 二进制[0011 0001]补码
// = 十进制[49]
System.out.println(a ^ b); // 输出值49
// 从右往左依次按位进行比较
// -60 = 二进制[1100 0100]补码
// 13 = 二进制[0000 1101]补码
// ------ ^ 按位异或运算 ------
// = 二进制[1100 1001]补码 逆推原码
// = 二进制[1100 1000]反码
// = 二进制[1011 0111]原码
// = 十进制[-55]
System.out.println(c ^ d); // 输出值-55
System.out.println("------------------- ~ 按位取反运算(按位非) -------------------");
// ~ 将参与运算的一个值转换为二进制按位进行 ‘取反’ 运算操作
// 取反操作属于一元运算,当二进制位数值为 0 时,取反后为 1 ;当二进制位数值为 1 时,取反后为 0
// 从右往左依次按位进行比较
// 60 = 二进制[0011 1100]补码
// ------ ~ 按位取反运算(按位非) ------
// = 二进制[1100 0011]补码 逆推原码
// = 二进制[1100 0010]反码
// = 二进制[1011 1101]原码
// = 十进制[-61]
System.out.println(~ a); // 输出值-61
// 从右往左依次按位进行比较
// -60 = 二进制[1100 0100]补码
// ------ ~ 按位取反运算(按位非) ------
// = 二进制[0011 1011]补码
// = 十进制[59]
System.out.println(~ c); // 输出值59
System.out.println("------------------- << 左移运算 -------------------");
// << 左移运算 含义相当于十进制 ×2 例子:1 << 2 等同于 1 × 2 × 2
// 公式 m << n = m × 2^n,m 为所有正负数,0除外,且n >= 0 ,因为n < 0时结果为0
// m << n 将m的二进制数(Java中的补码表示)左移 n 位,右边补0
System.out.println(a << 2); // 左移2位,输出值240
System.out.println(c << 2); // 左移2位,输出值-240
System.out.println("------------------- >> 右移运算 -------------------");
// >> 右移运算 含义相当于十进制 ÷2 例子:4 >> 2 等同于 4 ÷ 2 ÷ 2
// 公式 m << n = m × 0.5^n,m 为所有正负数,0除外,且n >= 0 ,因为n < 0时结果为0
// m >> n 将m的二进制数(Java中的补码表示)右移 n 位,正数右移,高位用0补,负数右移,高位用1补
// 从右往左依次按位进行比较
// 60 = 二进制[0011 1100]补码
// ------ >> 2 ------
// = 二进制[0000 1111]补码
// = 十进制[15]
// 从右往左依次按位进行比较
// -60 = 二进制[1100 0100]补码
// ------ >> 2 ------
// = 二进制[1000 1111]补码
// = 十进制[59]
System.out.println(a >> 2); // 右移2位,输出值15
System.out.println(c >> 2); // 右移2位,输出值-15
System.out.println("------------------- >>> (无符号右移) -------------------");
// >>> (无符号右移)与 >> 右移运算区别便是没有符号,无符号右移则不论正负高位全部补0
System.out.println(a >>> 2); // 无符号右移2位,输出值15
// 从右往左依次按位进行比较
// -60 = 二进制[1100 0100]补码
// ------ >>> 2 ------
// = 二进制[0011 1101]补码
// = 十进制[61]
// 是不是发现和下面的输出值对应不上
// 在java中int型占用4个字节,一个字节对应8位,也就是int型是32位
// -60 = 二进制[11111111 11111111 11111111 00111100]原码,高位都用1表示负数
// = 二进制[11111111 11111111 11111111 11000011]反码
// = 二进制[11111111 11111111 11111111 11000100]补码
// ------ >>> 2 ------
// = 二进制[00111111 11111111 11111111 11110001]补码
// = 十进制[1073741809]
// 在java中使用>>> (无符号右移)时最好都使用数值类型对应的字节去表示2进制位数,保证数据计算准确
System.out.println(c >>> 2); // 无符号右移2位,输出值1073741809
}
}
条件运算符( ? : )
- I = A ? X : Y 如果A为真(true),则I值为X,否则I值为Y
public class ConditionalOperator {
public static void main(String[] args) {
System.out.println("===================条件运算符===================");
// 条件运算符:? : (又叫三目运算符)
int i = 65;
String result = i < 60 ? "不及格" : "及格";
System.out.println(result); // 输出值及格
}
}
扩展赋值运算符(+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, >>>=)
- += a+=b 为 a = a + b 的简写
- -= a-=b 为 a = a - b 的简写
- *= a *=b 为 a = a * b 的简写
- /= a/=b 为 a = a / b 的简写
public class ExtendedAssignmentOperator {
public static void main(String[] args) {
System.out.println("===================扩展赋值运算符===================");
// 扩展赋值运算符:+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, >>>=
int a = 10;
int b = 20;
System.out.println("------------------- += 运算 -------------------");
// a += b 为 a = a + b 的简写
a += b;
System.out.println(a); // 输出值30
System.out.println(b); // 输出值20
System.out.println("------------------- -= 运算 -------------------");
// a -= b 为 a = a - b 的简写
a = 10;
b = 20;
a -= b;
System.out.println(a); // 输出值-10
System.out.println(b); // 输出值20
System.out.println("------------------- *= 运算 -------------------");
// a *= b 为 a = a * b 的简写
a = 10;
b = 20;
a *= b;
System.out.println(a); // 输出值200
System.out.println(b); // 输出值20
System.out.println("------------------- /= 运算 -------------------");
// a /= b 为 a = a / b 的简写
a = 10;
b = 20;
a /= b;
System.out.println(a); // 输出值0
System.out.println(b); // 输出值20
System.out.println("------------------- %= 运算 -------------------");
// a %= b 为 a = a % b 的简写
a = 10;
b = 20;
a %= b;
System.out.println(a); // 输出值10
System.out.println(b); // 输出值20
System.out.println("------------------- &= 运算 -------------------");
// a &= b 为 a = a & b 的简写
a = 10;
b = 20;
a &= b;
System.out.println(a); // 输出值0
System.out.println(b); // 输出值20
System.out.println("------------------- |= 运算 -------------------");
// a |= b 为 a = a | b 的简写
a = 10;
b = 20;
a |= b;
System.out.println(a); // 输出值30
System.out.println(b); // 输出值20
System.out.println("------------------- ^= 运算 -------------------");
// a ^= b 为 a = a ^ b 的简写
a = 10;
b = 20;
a ^= b;
System.out.println(a); // 输出值30
System.out.println(b); // 输出值20
System.out.println("------------------- <<= 运算 -------------------");
// a <<= b 为 a = a << b 的简写
a = 10;
b = 20;
a <<= b;
System.out.println(a); // 输出值10485760
System.out.println(b); // 输出值20
System.out.println("------------------- >>= 运算 -------------------");
// a >>= b 为 a = a >> b 的简写
a = 10;
b = 20;
a >>= b;
System.out.println(a); // 输出值0
System.out.println(b); // 输出值20
System.out.println("------------------- >>>= 运算 -------------------");
// a >>>= b 为 a = a >>> b 的简写
a = 10;
b = 20;
a >>>= b;
System.out.println(a); // 输出值0
System.out.println(b); // 输出值20
a = -10;
b = 20;
a >>>= b;
System.out.println(a); // 输出值4095
System.out.println(b); // 输出值20
}
}
幂运算
- 需要借助工具进行运算,JDK自带工具类Math去实现复杂的运算
public class PowerOperator {
public static void main(String[] args) {
System.out.println("===================幂运算===================");
// Math为JDK自带数据计算工具包
double dpow1 = Math.pow(2, 3); // 输出值8.0,3为次方,该语句意为2的3次方
System.out.println(dpow1);
double dpow2 = Math.pow(3, 2); // 输出值9.0
System.out.println(dpow2);
System.out.println();
}
}
运算符优先级
- 在数学运算中运算都是从左向右进行的,而在Java语言中大部分运算符也是从左向右结合的,只有单目运算符、赋值运算符和三目运算符是从右向左结合的,也就是从右向左进行运算,例如乘法和加法是两个可结合的运算,这两个运算符左右两边的操作数可以互换位置而不会影响运算结果
- 运算符有不同的优先级,优先级就是在表达式运算中的运算顺序
- 一般而言,单目运算符优先级较高,赋值运算符优先级较低。算术运算符优先级较高,关系和逻辑运算符优先级较低
优先级顺序如下表格,数字越小优先级越高
运算符 | 优先级 |
---|---|
++, --, !, ~ | 1 |
*, /, % | 2 |
+, - | 3 |
>>, <<, >>> | 4 |
>, <, >= <=, instanceof(面向对象会学到) | 5 |
==, != | 6 |
& | 7 |
^ | 8 |
| | 9 |
&& | 10 |
|| | 11 |
?: | 12 |
+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, >>>= | 13 |
PS:一般程序开发中推荐使用圆括号直接标出优先计算的程序,提高程序可读性,更加直观