运算符
运算符丰富是 Java 语言的主要特点之一,它提供的运算符数量之多,在高级语言中是少见的。
Java 语言中的运算符除了具有优先级之外,还有一个结合性的特点。当一个表达式中出现多种运算符时,执行的先后顺序不仅要遵守运算符优先级别的规定,还要受运算符结合性的约束,以便确定是自左向右进行运算还是自右向左进行运算。这些运算符按照操作数的数量可以分为单目运算符、双目运算符和三目运算符。
最基本的运算符包括算术运算符、赋值运算符、逻辑运算符和关系运算符等
算术运算符
一元运算符(含自增自减内容)
算术一元运算一共有 3 个,分别是 -、++ 和 --。
运 算 符 | 名 称 | 说 明 | 例 子 |
---|---|---|---|
- | 取反符号 | 取反运算 | b=-a |
++ | 自加一 | 先取值再加一,或先加一再取值 | a++ 或 ++a |
-- | 自减一 | 先取值再减一,或先减一再取值 | a-- 或 --a |
表中,-a 是对 a 取反运算,a++ 或 a-- 是在表达式运算完后,再给 a 加一或减一。而 ++a 或 --a 是先给 a 加一或减一,然后再进行表达式运算。
运算符 | 含义 | 实例 | 结果 |
---|---|---|---|
i++ | 将 i 的值先使用再加 1 赋值给 i 变量本身 | int i=1; int j=i++; | i=2 j=1 |
++i | 将 i 的值先加 1 赋值给变量 i 本身后再使用 | int i=1; int j=++i; | i=2 j=2 |
i-- | 将 i 的值先使用再减 1 赋值给变量 i 本身 | int i=1; int j=i--; | i=0 j=1 |
--i | 将 i 的值先减 1 后赋值给变量 i 本身再使用 | int i=1; int j=--i; | i=0 j=0 |
在使用自增/自减运算时应注意下面几个问题。
-
自增/自减只能作用于变量,不允许对常量、表达式或其他类型的变量进行操作。常见的错误是试图将自增或自减运算符用于非简单变量表达式中。
-
自增/自减运算可以用于整数类型 byte、short、int、long,浮点类型 float、double,以及字符串类型 char。
-
在 Java 1.5 以上版本中,自增/自减运算可以用于基本类型对应的包装器类 Byte、Short、Integer、Long、Float、Double 和 Character。
-
自增/自减运算结果的类型与被运算的变量类型相同。
‘自增自减’
int x = 5, y; // 声明用于自增和自减的整型变量 char cx = 'B', cy; // 声明用于自增和自减的字符型变量 float fx = 5.5f, fy; // 声明用于自增和自减的浮点型变量 System.out.println("---------对整数的自增和自减---------"); y = x++; System.out.printf("y=x++ 的结果为:%d ,%d \n", x, y); y = x--; System.out.printf("y=x-- 的结果为:%d ,%d \n", x, y); y = ++x; System.out.printf("y=++x 的结果为:%d ,%d \n", x, y); y = --x; System.out.printf("y=--x 的结果为:%d ,%d \n", x, y); System.out.println("\n---------对浮点的自增和自减---------"); fy = fx++; System.out.printf("fy=fx++ 的结果为:%f ,%f \n", fx, fy); fy = fx--; System.out.printf("fy=fx-- 的结果为:%f ,%f \n", fx, fy); fy = ++fx; System.out.printf("fy=++fx 的结果为:%f ,%f \n", fx, fy); fy = --fx; System.out.printf("fy=--fx 的结果为:%f ,%f \n", fx, fy); System.out.println("\n---------对字符的自增和自减---------"); cy = cx++; System.out.printf("cy=cx++ 的结果为:%c ,%c \n", cx, cy); cy = cx--; System.out.printf("cy=cx-- 的结果为:%c ,%c \n", cx, cy); cy = ++cx; System.out.printf("cy=++cx 的结果为:%c ,%c \n", cx, cy); cy = --cx; System.out.printf("cy=--cx 的结果为:%c ,%c \n", cx, cy);
---------对整数的自增和自减---------
y=x++ 的结果为:6 ,5
y=x-- 的结果为:5 ,6
y=++x 的结果为:6 ,6
y=--x 的结果为:5 ,5
---------对浮点的自增和自减---------
fy=fx++ 的结果为:6.500000 ,5.500000
fy=fx-- 的结果为:5.500000 ,6.500000
fy=++fx 的结果为:6.500000 ,6.500000
fy=--fx 的结果为:5.500000 ,5.500000
---------对字符的自增和自减---------
cy=cx++ 的结果为:C ,B
cy=cx-- 的结果为:B ,C
cy=++cx 的结果为:C ,C
cy=--cx 的结果为:B ,B
二元运算符
Java 语言中算术运算符的功能是进行算术运算,除了经常使用的加(+)、减(-)、乘()和除(\)外,还有取模运算(%)。加(+)、减(-)、乘()、除(\)和我们平常接触的数学运算具有相同的含义。
运 算 符 | 名 称 | 说 明 | 例 子 |
---|---|---|---|
+ | 加 | 求 a 加 b 的和,还可用于 String 类型,进行字符串连接操作 | a + b |
- | 减 | 求 a 减 b 的差 | a - b |
* | 乘 | 求 a 乘以 b 的积 | a * b |
/ | 除 | 求 a 除以 b 的商 | a / b |
% | 取余 | 求 a 除以 b 的余数 | a % b |
算术运算符都是双目运算符,即连接两个操作数的运算符。优先级上,*、/、% 具有相同运算级别,并高于 +、-(+、- 具有相同级别)。
‘四种类型的二元运算’
float f1 = 9 % 4;// 保存取余后浮点类型的结果
double da = 9 + 4.5; // 双精度加法
double db = 9 - 3.0; // 双精度减法
double dc = 9 * 2.5; // 双精度乘法
double dd = 9 / 3.0; // 双精度除法
double de = 9 % 4; // 双精度取余
System.out.println("整数的算术运算"); // 整数的加、减、乘、除和取余
System.out.printf("9+4=%d \n", 9 + 4);
System.out.printf("9-4=%d \n", 9 - 4);
System.out.printf("9*4=%d \n", 9 * 4);
System.out.printf("9/4=%d \n", 9 / 4);
System.out.printf("9%%4=%d \n", 9 % 4);
System.out.println("\n浮点数的算术运算"); // 浮点数的加、减、乘、除和取余
System.out.printf("9+4.5f=%f \n", 9 + 4.5f);
System.out.printf("9-3.0f=%f \n", 9 - 3.0f);
System.out.printf("9*2.5f=%f \n", 9 * 2.5f);
System.out.printf("9/3.0f=%f \n", 9 / 3.0f);
System.out.printf("9%%4=%f \n", f1);
System.out.println("\n双精度数的算术运算"); // 双精度数的加、减、乘、除和取余
System.out.printf("9+4.5=%4.16f \n", da);
System.out.printf("9-3.0=%4.16f \n", db);
System.out.printf("9*2.5=%4.16f \n", dc);
System.out.printf("9/3.0=%4.16f \n", dd);
System.out.printf("9%%4=%4.16f \n", de);
System.out.println("\n字符的算术运算"); // 对字符的加法和减法
System.out.printf("'A'+32=%d \n", 'A' + 32);
System.out.printf("'A'+32=%c \n", 'A' + 32);
System.out.printf("'a'-'B'=%d \n", 'a' - 'B');
整数的算术运算
9+4=13
9-4=5
9*4=36
9/4=2
9%4=1
浮点数的算术运算
9+4.5f=13.500000
9-3.0f=6.000000
9*2.5f=22.500000
9/3.0f=3.000000
9%4=1.000000
双精度数的算术运算
9+4.5=13.5000000000000000
9-3.0=6.0000000000000000
9*2.5=22.5000000000000000
9/3.0=3.0000000000000000
9%4=1.0000000000000000
字符的算术运算
'A'+32=97
'A'+32=a
'a'-'B'=31
本示例中使用了 4 种类型来执行算术运算。其中,整数类型的结果最容易理解,浮点型和双精度型返回的结果都带有小数,字符型将会把字符转换为 ASCII 码再运算。
从输出结果中可以看到,整数之间的运算结果只保留整数部分,浮点型运算时保留 6 位小数部分,双精度运算时则保留 16 位小数部分。
注意:Java 语言算术运算符的优先级是先乘除后加减
算术赋值运算符
算术赋值运算符只是一种简写,一般用于变量自身的变化。
运 算 符 | 名 称 | 例 子 |
---|---|---|
+= | 加赋值 | a += b、a += b+3 |
-= | 减赋值 | a -= b |
*= | 乘赋值 | a *= b |
/= | 除赋值 | a /= b |
%= | 取余赋值 | a %= b |
‘示例’
int a = 1;
int b = 2;
a += b; // 相当于 a = a + b
System.out.println(a); // 3
a += b + 3; // 相当于 a = a + b + 3
System.out.println(a); // 8
a -= b; // 相当于 a = a - b
System.out.println(a); // 6
a *= b; // 相当于 a=a*b
System.out.println(a); // 12
a /= b; // 相当于 a=a/b
System.out.println(a); // 6
a %= b; // 相当于 a=a%b
System.out.println(a); // 0
赋值运算符
赋值运算符是指为变量或常量指定数值的符号。赋值运算符的符号为“=”,它是双目运算符,左边的操作数必须是变量,不能是常量或表达式。
格式:
变量名称 = 表达式内容
其中,变量名称”和“表达式”内容的类型必须匹配,如果类型不匹配则需要自动转化为对应的类型。
赋值运算符和算数运算符也可以组成复合赋值运算,如下表所示:
运算符 | 含义 | 实例 | 结果 |
---|---|---|---|
+= | 将该运算符左边的数值加上右边的数值, 其结果赋值给左边变量本身 | int a=5; a+=2; | a=7 |
-= | 将该运算符左边的数值减去右边的数值, 其结果赋值给左边变量本身 | int a=5; a-=2; | a=3 |
*= | 将该运算符左边的数值乘以右边的数值, 其结果赋值给左边变量本身 | int a=5; a*=2; | a=10 |
/= | 将该运算符左边的数值整除右边的数值, 其结果赋值给左边变量本身 | int a=5; a/=2; | a=2 |
%= | 将该运算符左边的数值除以右边的数值后取余,其结果赋值给左边变量本身 | int a=5; a%=2; | a=1 |
‘赋值运算表达式’
int x, y, z; // 定义3个整型的变量
x = y = z = 6; // 为变量赋初值为6
x += 10; // 等价于x=x+10,结果x=16
y -= 3; // 等价于y=y-3,结果y=3
z *= 5; // 等价于z=z*5,结果z=30
x /= 4; // 等价于x=x/4,结果x=4
z %= x; // 等价于z=z%x,结果z=2
注意:虽然 Java 支持一次为多个变量赋值的写法,但这种写导致程序的可读性降低,因此不推荐。
逻辑运算符
逻辑运算符把各个运算的关系表达式连接起来组成一个复杂的逻辑表达式,以判断程序中的表达式是否成立,判断的结果是 true 或 false。逻辑运算符是对布尔型变量进行运算,其结果也是布尔型。
逻辑运算符的含义及用法:
运算符 | 用法 | 含义 | 说明 | 实例 | 结果 |
---|---|---|---|---|---|
&& | a&&b | 短路与 | ab 全为 true 时,计算结果为 true,否则为 false。 | 2>1&&3<4 | true |
|| | a||b | 短路或 | ab 全为 false 时,计算结果为 false,否则为 true。 | 2<1||3>4 | false |
! | !a | 逻辑非 | a 为 true 时,值为 false,a 为 false 时,值为 true | !(2>4) | true |
| | a|b | 逻辑或 | ab 全为 false 时,计算结果为 false,否则为 true | 1>2|3>5 | false |
& | a&b | 逻辑与 | ab 全为 true 时,计算结果为 true,否则为 false | 1<2&3<5 | true |
- &&还具有短路的功能,即如果第一个表达式为false,则不再计算第二个表达式
- &还可以用作位运算符,当&操作符两边的表达式不是boolean类型时,&表示按位与操作,我们通常使用0x0f来与一个整数进行&运算,来获取该整数的最低4个bit位,例如,0×31 & 0x0f的结果为0×01。
- ||只要满足第一个条件,后面的条件就不再判断,而|要对所有的条件进行判断。也就是说:“|”不存在短路
注意:短路与(&&)和短路或(||)能够采用最优化的计算方式,从而提高效率。在实际编程时,应该优先考虑使用短路与和短路或。
逻辑运算符的优先级为:!运算级别最高,&& 运算高于 || 运算。!运算符的优先级高于算术运算符,而 && 和 || 运算则低于关系运算符。结合方向是:逻辑非(单目运算符)具有右结合性,逻辑与和逻辑或(双目运算符)具有左结合性。
关系运算符
关系运算符(relational operators)也可以称为“比较运算符”,用于用来比较判断两个变量或常量的大小。关系运算符是二元运算符,运算结果是 boolean 型。当运算符对应的关系成立时,运算结果是 true,否则是 false。
关系运算符及其含义说明:
运算符 | 含义 | 说明 | 实例 | 结果 |
---|---|---|---|---|
> | 大于运算符 | 只支持左右两边操作数是数值类型。如果前面变量的值大于后面变量的值, 则返回 true。 | 2>3 | false |
>= | 大于或等于运算符 | 只支持左右两边操作数是数值类型。如果前面变量的值大于等于后面变量的值, 则返回 true。 | 4>=2 | true |
< | 小于运算符 | 只支持左右两边操作数是数值类型。如果前面变量的值小于后面变量的值,则返回 true。 | 2<3 | true |
<= | 小于或等于运算符 | 只支持左右两边操作数是数值类型。如果前面变量的值小于等于后面变量的值, 则返回 true。 | 4<=2 | false |
== | 相等运算符 | 如果进行比较的两个操作数都是数值类型,无论它们的数据类型是否相同,只要它们的值相等,也都将返回 true。 如果两个操作数都是引用类型,只有当两个引用变量的类型具有父子关系时才可以比较,只要两个引用指向的不是同一个对象就会返回 true。 Java 也支持两个 boolean 类型的值进行比较。 | 4 == 4;97 == 'a';5.0 == 5;true==false | true true true false |
!= | 不相等运算符 | 如果进行比较的两个操作数都是数值类型,无论它们的数据类型是否相同,只要它们的值不相等,也都将返回 true。 如果两个操作数都是引用类型,只有当两个引用变量的类型具有父子关系时才可以比较,只要两个引用指向的不是同一个对象就会返回 true。 | 4!=2 | true |
注意:
- 基本类型的变量、值不能和引用类型的变量、值使用 == 进行比较;boolean 类型的变量、值不能与其他任意类型的变量、值使用 == 进行比较;如果两个引用类型之间没有父子继承关系,那么它们的变量也不能使用 == 进行比较。
- == 和 != 可以应用于基本数据类型和引用类型。当用于引用类型比较时,比较的是两个引用是否指向同一个对象,但当时实际开发过程多数情况下,只是比较对象的内容是否相当,不需要比较是否为同一个对象。
关系运算符的优先级为:>、<、>=、<= 具有相同的优先级,并且高于具有相同优先级的 !=、==。关系运算符的优先级高于赋值运算符而低于算术运算符,结合方向是自左向右。
位运算符
Java 定义的位运算(bitwise operators)直接对整数类型的位进行操作,这些整数类型包括 long,int,short,char 和 byte。
位运算符主要用来对操作数二进制的位进行运算。按位运算表示按每个二进制位(bit)进行计算,其操作数和运算结果都是整型值。
Java 语言中的位运算符分为位逻辑运算符和位移运算符两类。
位逻辑运算符
位逻辑运算符包含 4 个:&(与)、|(或)、~(非)和 ^(异或)。除了 ~(即位取反)为单目运算符外,其余都为双目运算符。
按位与运算
按位与运算符"&"是双目运算符。 其功能是参与运算的两数各对应的二进位相与。只有对应的两个二进位均为1时,结果位才为1 ,否则为0。参与运算的数以补码方式出现。
例如:9&5可写算式如下: 00001001 (9的二进制补码)&00000101 (5的二进制补码) 00000001 (1的二进制补码)可见9&5=1。 按位与运算通常用来对某些位清0或保留某些位。例如把a 的高八位清 0 , 保留低八位, 可作 a&255 运算 ( 255 的二进制数为11111111)。
‘Java位与运算’
int a=9,b=5,c;
c=a&b;
System.out.printf("a=%d\nb=%d\nc=%d\n",a,b,c);
// a=9
// b=5
// c=1
按位或运算
按位或运算符“|”是双目运算符。 其功能是参与运算的两数各对应的二进位相或。只要对应的二个二进位有一个为1时,结果位就为1。参与运算的两个数均以补码出现。
9|5
00001001
|
00000101
=00001101
00001101十进制为13,所以9|5 = 13.
‘’
int a=9,b=5,c;
c=a|b;
System.out.printf("a=%d\nb=%d\nc=%d\n",a,b,c); // c = 13
按位异或运算
按位异或运算符“^”是双目运算符。 其功能是参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。参与运算数仍以补码出现。
'9^5'
00001001
^
00000101
=00001100
求反运算
求反运算符~为单目运算符,具有右结合性。 其功能是对参与运算的数的各二进位按位求反。
如:
~000110
=111001
注意:位运算符的操作数只能是整型或者字符型数据以及它们的变体,不用于 float、double 或者 long 等复杂的数据类型。
位移运算符
左移运算符
左移运算符,是双目运算符。左移n位就是乘以2的n次方。 其功能把左边的运算数的各二进位全部左移若干位,由右边的数指定移动的位数,高位丢弃,低位补0。
(丢弃最高位,0补最低位)
1.例: a<<4 指把a的各二进位向左移动4位。如a=00000011(十进制3),左移4位后为00110000(十进制48)。
2.例: int i = 1; i = i << 2; //把i里的值左移2位 也就是说,1的2进制是000...0001(这里1前面0的个数和int的位数有关,32位机器,gcc里有31个0),左移2位之后变成 000...0100,也就是10进制的4,所以说左移1位相当于乘以2,那么左移n位就是乘以2的n次方了
右移运算符
右移运算符,是双目运算符。右移n位就是除以2的n次方
其功能是把左边的运算数的各二进位全部右移若干位,“>>”右边的数指定移动的位数。
例如:设 a=15,a>>2 表示把00001111右移为00000011(十进制3)。 应该说明的是,对于有符号数,在右移时,符号位将随同移动。当为正数时, 最高位补0,而为负数时,符号位为1,最高位是补0或是补1 取决于编译系统的规定。
右移对符号位的处理和左移不同: 对于有符号整数来说,比如int类型,右移会保持符号位不变。
‘示例’
x>>1;//相当于x/=2
x<<1;//相当于x*=2
x>>2;//x/=4
x<<2;//x*=4
x>>3;//x/=8
x<<3;//x*=8