表达式是由运算符和操作数组成,对操作数据进行运算符指定的操作,并得出一个结果。操作数可以是变量、常量或方法调用等(变量和常量的定义)。运算符用来将一个或多个操作数连缀成执行语句,以实现特定功能。表达式可用来计算一个公式,为变量赋值以及帮助控制程序的执行流程。
1. 运算符分类
Java中的运算符按照操作数的数量可分为三种类型:一元运算符、二元运算符、三元运算符。只有一个操作数的运算符称为一元运算符,例如,++、--都是一元运算符。需要两个操作的运算符称为二元运算符,例如,加号(+)、赋值号(=)都是二元运算符。需要三个操作数的运算符称为三元运算符,Java中只有一个三元运算符是“? :”。Java中的运算符按照功能可以分为算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符和条件运算符等,除此之外,还有几类特殊的运算符,如,数组下标运算符([])、点运算符(.)、new运算符、实例运算符(instanceof)等。
2. 算术运算符
算术运算符用于执行基本的数学运算,Java算术运算符包括:加(+)、减(-)、乘(*)、除(/)、取模(%)、自增(++)、自减(--),此外,+还可以表示正号,-还可以表示负号。
2.1. 四则运算
加(+)、减(-)、乘(*)、除(/)为四则运算运算符,它们都是为二元运算符,两个操作数的数据类型可以是整型、浮点型和字符型,不同类型的操作数可以进行混合运算,但是要进行相应的转换(Java基本数据类型之间的转换)。
下面为两个整数的加、减、乘、除运算示例:
int a=5,b=10,c=0; //声明三个整型变量
c=a+b; //两个整数相加,结果为15
c=b-a; //两个整数相减,结果为5
c=a*b; //两个整数相乘,结果为50
c=a/b; //两个整数相除,结果为0
c=b/a; //两个整数相除,结果为2
下面为两个浮点数的加、减、乘、除运算示例:
double x=2.0,y=3.6,z=0; //声明三个双精度浮点型变量
z=x+y; //两个双精度浮点数相加,结果为5.6
z=x-y; //两个双精度浮点数相减,结果为-1.6
z=x*y; //两个双精度浮点数相乘,结果为7.2
z=y/x; //两个双精度浮点数相除,结果为1.8
如果除(/)的两个操作数都是整数类型,则除数不能是0,但是如果有一个是浮点数或者两个都是浮点数,则允许除数是0或者0.0,结果为正无穷大(Infinity)或者负无穷大(-Infinity),示例如下:
double x=2.0,y=-3.6,z=0; //声明三个双精度浮点型变量
z=x/0.0; //正浮点数除以浮点数0,结果为正无穷Infinity
z=x/0; //正浮点数除以整数0,结果为正无穷Infinity
z=y/0.0; //负浮点数除以浮点数0,结果为负无穷Infinity
z=y/0; //负浮点数除以整数0,结果为负无穷Infinity
整数类型和浮点类型数可以进行混合运算,运算前需要进行类型转换 (Java基本数据类型之间的转换),示例如下:
int a=5,c=0; //声明两个整型变量
double y=3.6,z=0; //声明两个双精度浮点型变量
z=a*y; //整数与浮点数相乘,整数自动转换为浮点型,结果为浮点数18.0
c=(int)y*a; //将浮点数转换为整数后与另一个整数相乘,结果为整数18
由于一个字符对应一个整数,因此,字符型变量之间也可以进行四则运算。
char ch1='a',ch2=98; //'a'对应的整数为97,字符‘b’对应的整数为98
int ch3=ch1+ch2; //ch3=97+98=195
另外,两个字符串之间也可以用+运算符进行连接。
String str1="abc",str2="def";
String str=str1+str2; //str="abcdef"
2.2. 取模运算符
取模(%)运算符为二元运算符,其结果为第一个操作数除以第二个操作数后的余数。如果两个操作数都为整数类型,则除数不能为0,否则会引发除以0异常,但是,如果两个操作操作数有一个是浮点数或者两个都是浮点数,此时允许除数是0或0.0,结果是NaN。
下面为取模运算符示例:
int a=5,b=10,c=0; //声明三个整型变量
c=a%b; //整数a除以整数b后取余数,结果为5
c=b%a; //整数b除以整数a后取余数,结果为0
double x=2.0,y=-3.6,z=0; //声明三个双精度浮点型变量
z=y%x; //浮点数y除以浮点数x后取余数,结果为1.6
z=x%y; //浮点数x除以浮点数y后取余数,结果为2.0
z=x%0; //浮点数x除以浮点数0.0后取余数,结果为NaN
2.3. 自增与自减
++是自增运算符,其结果是将操作数在原来的基础上加1;--是自减运算符,其结果是将操作数在原来的基础上减1。++和—既可以放在操作数的前面,也可以放在操作数的后面。++放在操作数的前面称为前缀自增,前缀自增是先把操作数自增1后再放入其所在的表达式中运算;++放在操作数的后面称为后缀自增,后缀自增是先使用操作数的原值,当其所在的表达式运算结束后再将操作数自增1。--放在操作数的前面称为后缀前缀自减,前缀自减是先把操作数自减1后再放入其所在的表达式中运算;--放在操作数的后面称为后缀自减,后缀自减是先使用该操作的原值,当其所在的表达式运算结束后再将操作数自减1。
前缀自增示例 | int i=0; int j=++i; System.out.println("i="+i+",j="+j);//输出:i=1,j=1 |
后缀自增示例 | int i=0; int j=i++; System.out.println("i="+i+",j="+j);//输出:i=1,j=0 |
前缀自减示例 | int i=0; int j=--i; System.out.println("i="+i+",j="+j);//输出:i=-1,j=-1 |
后缀自减示例 | int i=0; int j=i--; System.out.println("i="+i+",j="+j);//输出:i=-1,j=0 |
3. 关系运算符
关系运算符是二元运算符,用来对两个数值(整数类型、浮点数类型、字符类型)进行比较,其结果为一个布尔值。关系运算符包括:大于(>)、大于等于(>=)、小于(<)、小于等于(<=)、等于(==)、不等于(!=)六种,如下表所示。
名称 | 运算符 | 表达式示例 | 运算结果 |
大于 | > | 3<2 | true |
大于等于 | >= | 6>=6 | true |
小于 | < | ‘a’<’b’ | true |
小于等于 | <= | 7.2<=6.5 | false |
等于 | == | 1==1 | true |
不等于 | != | 2!=2 | false |
4. 逻辑运算符
逻辑运算符用来对布尔型的数据进行操作,其结果仍是一个布尔型数据。逻辑运算符包括:与(&)、或(|)、非(!)、异或(^)、短路与(&&)、短路或(||)六种,如下表所示。
操作数1(a) | 操作数2(b) | a&b | a|b | !a | a^b | a&&b | a||b |
false | false | false | false | true | false | false | false |
false | true | false | true | true | true | false | true |
true | false | false | true | false | true | false | true |
true | true | true | true | false | false | true | true |
尽管运算符&和&&都表示与操作,但是当运算符的右边为表达式时,两者还是有一定差异。在使用&进行运算时,不论左边为true或者false,右边的表达式都会进行运算;如果使用&&进行运算时,当左边为false时,右边的表达式不会进行运算,因此,&&被称为短路与。类似地,||表示短路或,当运算符||的左边为true时,右边的表达式不会进行运算。
int x=0,y=0,z=0;
boolean a,b,c,d;
a = x>0 & y++>1;
b = x>0 && z++>1;
System.out.println("a="+a+",b="+b); //结果为a=false,b=false
System.out.println("y="+y+",z="+z); // 结果为y=1,z=0
y=0;z=0;
c = x==0 | y++>1;
d = x==0 || z++>1;
System.out.println("c="+c+",d="+d); //结果为a=true,b=true
System.out.println("y="+y+",z="+z); //结果为y=1,z=0
5. 位运算符
位运算符是针对二进制数的每一位进行运算的符号,它是专门针对数字0和1进行操作的。位运算符包括:按位与(&)、按位或(|)、按位取反(~)、按位异或(^)、右移(>>)、左移(<<)、无符号右移(>>>)。位运算只能对整型和字符型数据进行操作。
名称 | 符号 | 描述 | 示例 |
按位与 | & | 当两位同时为1时才能返回1,否则返回0 | 00011000 &11110011=00010000 |
按位或 | | | 只要有1位为1即可返回1 | 00011000 | 11110011=11111011 |
按位取反 | ~ | 0变成1,1变成0 | ~00011000 = 11100111 |
按位异或 | ^ | 两位相同时返回0,不同时返回1 | 00011000 ^ 11110011=11101011 |
右移 | >> | i>>n表示将i右移n位,左边空出来的空位如果是整数则填充0;如果是负数则填充1,相当于除以2的n次方 | 00011000 >> 2=00000110 11110011 >> 2=11111100 |
左移 | << | i<<n表示将i左移n位,右边空出来的位填充0,相当于乘以2的n次方 | 00011000 << 2=01100000 11110011 << 2=11001100 |
无符号右移 | >>> | i>>>n表示将i右移n位,左边空出来的空位填充0 | 00011000 >>> 2=00000110 11110011 >>> 2=00111100 |
Java中使用补码来表示二进制数,在补码表示中最高位为符号位,正数的符号为是0,负数的符号位是1。正数的补码与原码相同。负数的补码符号位为1,其余位为该数绝对值的原码按位取反,然后整个数加1。
例如,字节型(byte)的数30的原码位00011110,因此其补码也为00011110。对于字节型(byte)的数-30,由于是负数,符号位为1,其它位是30的原码,整个数为10011110,按位取反后变成11100001,再加1后变成11100010,因此,-30的补码是11100010。
已知一个数的补码,如何求原码?如果补码的符号位为”0”,表示是一个正数,所以补码就是该数的原码。如果补码的符号位为”1”,表示是一个负数,求原码的操作可以是:符号位为1,其余各位取反,然后再整个数加1。
例如,一个数的补码为11100010,则原码为10011110(-30)。
因为符号位为”1”,表示是一个负数,所以该位不变,仍为”1” ,其余7位1100010取反后为0011101,再加1,所以是10011110。
6. 条件运算符
条件运算符(?:)是三元运算符,它一般形式为:
表达式1?表达式2:表达式3;
其中,表达式1的结果是一个结果为布尔值的逻辑表达式。首先计算表达式1的值,当表达式1的结果为true时,则将表达式2的值作为条件运算的结果;否则,将将表达式3的值作为条件运算的结果。
条件运算符应用示例:
int a=100,b=90,result;
result=a>b?1:-1; //result的值为1
result=a>b?a:b; //result的值为100
result=a<b?(a+=10):(b++);//result的值为90,a的值为100,b的值为91
在上面的最后一个语句中,因为a<b的结果为false,所以执行表达式b++, 该表达式先返回b的值(90),然后b再增1,即b最后的值为91。
7. 赋值运算符
简单的赋值运算符时把一个表达式的值直接赋给一个变量,其格式如下:
变量 = 表达式;
在赋值运算符“=”两侧类型不一致的情况下,则按照2.4.3节介绍的规则进行强制转换或自动转换。
在赋值运算符“=”前面加上其它运算符(算术运算符或位运算符),就构成了扩展赋值运算符,扩展赋值运算符的格式如下:
变量 运算符= 表达式;
上面的表达式等价于:
变量 = 变量 运算符 表达式;
例如,a=a+8;
可以写成如下扩展赋值运算表达式:
a+=8; //等价于a=a+8
8. 运算符的优先级与结合性
运算符的优先级是指同一表达式中多个运算符被执行的先后次序。在表达式求值时,需要按照运算符的优先级由高到底的次序执行。运算符从高到底的一般次序为:一元运算符、算术运算符、位运算符、关系运算符、逻辑运算符、赋值运算符。运算符除了优先级外,还有结合性,运算符的结合性决定了并列的多个同级运算符的先后执行顺序。大部分运算符的结合性是“自左向右”,而赋值运算符、一元运算符等则是“自右向左”的。
例如,
int a=100,b=90,result;
result=a-10+b; //先计算a-10,等于90;再计算90+b,结果等于180
result=a+=b=10; //先计算b=10;再计算a+=10,结果为110;最后进行赋值,结果为10
下表列出了各种运算符优先级和结合性,数字越小表示优先级别越高。
优先级 | 运算符 | 运算符类型 | 结合性 |
1 | . , [], () | 点运算符、数组下标运算符、括号运算符 | 自左向右 |
2 | ++, - -, !, ~, instanceof | 自增运算符、自减运算符、逻辑非运算符 按位取反运算符、对象实例运算符 | 自右向左 |
3 | new | 创建对象运算符 | 自右向左 |
4 | *, /, % | 乘、除、取模算术运算符 | 自左向右 |
5 | +, - | 加、减算术运算符 | 自左向右 |
6 | >>, >>>, << | 位左移、位右移、无符号左移运算符 | 自左向右 |
7 | < >, <=, >= | 小于、大于、小于等于、大于等于运算符 | 自左向右 |
8 | == , != | 等于、不等于关系运算符 | 自左向右 |
9 | & | 按位与运算符 | 自左向右 |
10 | ^ | 按位异或运算符 | 自左向右 |
11 | | | 按位或运算符 | 自左向右 |
12 | && | 逻辑与运算符 | 自左向右 |
13 | || | 逻辑或运算符 | 自左向右 |
14 | ?: | 条件运算符 | 自左向右 |
15 | = , +=, -=, *=, /=, %=, ^= | (扩展)赋值运算符 | 自右向左 |
16 | &= , |=, <<=, >>=, >>>= | 扩展赋值运算符 | 自右向左 |