- Java语言程序设计
- 陆迟编著
- 2532字
- 2020-08-27 13:55:03
2.4 运算符
运算符的作用是与一定的运算数据组成表达式来完成相应的运算。对不同的数据类型,有着不同的运算符。对运算符,有运算对象(操作数)个数及类型、运算优先级、结合性等特性。
根据运算对象的多少,Java的运算符可分为一元(或称单目)、二元(双目)和三元(三目)运算符。
运算符的优先级是指不同运算符在运算中执行的先后顺序。在Java语言中共有17种优先级,每个运算符分属确定的一个优先级别。Java语言严格按照运算符的优先级由高到低地顺序执行各种运算。
运算符的结合性确定同级运算符的运算顺序。左结合性规定,运算数据先与左边的运算符结合,然后与右边的运算符结合。右结合性刚好相反。
本节介绍一些基本的Java运算符。部分未介绍的运算符在以后的章节中陆续介绍。
2.4.1 算术运算符
算术运算符的操作数类型是数值类型。
1.一元算术运算符
表2.6列出了一元算术运算符。它们的结合性是右结合。
表2.6 一元运算符列表
+和-运算符使运算对象取正、负值,用得不多,但它们有提升操作数类型的作用。例如:
byte i=10,j; j = -i;
上述语句将产生编译错误,原因是i经过 - 运算后,已经提升为int类型,直接向字节变量j赋值是不允许的。
++和--既可以是前置运算符也是后置运算符,这就是说,它们既可以放在运算对象(必须是变量)前面(如++ x),也可以放在后面(如x ++)。单独使用的时候,前置后置作用相同。但若在表达式中使用,前置后置的意义是不同的。前置时,变量的值先增1 或减1,然后用变量的新值参加表达式的计算;后置时,变量的值先参加表达式的计算,然后变量再增1或减1。例如:
设i = 5;
j = i ++;
执行后,j为5,i为6。
而i = 5;
j = ++ i;
执行后,j为6,i为6。
【例2.2】说明++和--运算符的使用。
class IncrementDecrement { public static void main(String args[]) { int i,j,k; i = 1; k=(j=i++); System.out.println("i= "+i+" j="+j+" k= "+k); k=(i=2)*j--; System.out.println("i= "+i+" j="+j+" k= "+k); k=++i+ ++i+ ++i; System.out.println("i= "+i+" j="+j+" k="+k); k=i-- + i-- + i--; System.out.println("i= "+i+" j="+j+" k="+k); } }
程序运行结果如下:
i= 2 j=1 k= 1 i= 2 j=0 k= 2 i= 5 j=0 k=12 i= 2 j=0 k=12
2.二元算术运算符
二元算术运算符不改变运算对象的值,而是得到一个可以保存和输出的计算结果。表2.7列出了二元算术运算符。二元算术运算符具有左结合性。
表2.7 二元算术运算符
这些都是常用的运算,对二元算术运算符,有两点要注意:
(1)两个整数运算的结果是整数,5/2结果是2而不是2.5。
(2)取模运算是求两个数相除的余数,如17%3 的结果是2。可以对实数求余数。实数a%b的结果为a-(int)(a/b)*b,余数的符号与被除数a相同。如123.4%10的结果为3.4。
2.4.2 关系运算符
关系运算符都是双目运算符,用于确定一个数据与另一个数据之间的关系,即进行关系运算(比较运算,将两个值进行比较)。关系运算的结果值为true、false(布尔型)。表2.8列出了Java语言提供的6种关系运算符。
表2.8 关系运算符
在这里要指出的是,等于运算符==不要与赋值运算符=混淆,以致于关系运算变成了赋值运算。
关系运算符常用于if语句、循环语句的条件中。运算符“==”和“!=”的运算优先级低于另外四个关系运算符,同一优先级中遵循自左至右的执行顺序。
2.4.3 布尔运算符
布尔运算符可以对布尔类型的数据(布尔常量、布尔变量、关系表达式和布尔表达式等)进行运算,结果也为布尔类型。表2.9 列出了Java语言的布尔运算符,布尔运算规则见表2.10。
表2.9 布尔运算符
表2.10 布尔运算真值表
简洁与、或和非简洁与、或的结果有时不同。非简洁与、非简洁或运算时,运算符两边的表达式都先要运算执行,然后两表达式的结果再进行与、或运算。简洁与、简洁或运算时,若只运算左边表达式即可确定与、或结果时,则右边的表达式将不会被计算。
例如,int x = 2,y = 3,a = 4,b = 5;
boolean b = x ++ > y++ && a ++ > b ++;
则运算结果为:b = false, x = 3, y = 4, a = 4, b = 5
而boolean b = x ++ > y++ & a ++ > b ++;
运算结果为:b = false, x = 3, y = 4, a = 5, b = 6
几个布尔运算符中,单目布尔运算符!的优先级最高,而&又高于|。运算符!又高于算术运算符和关系运算符,运算符&、|低于关系运算符。布尔运算符的执行顺序为自左至右。在一个布尔表达式中,使用的运算符种类可能较多,应注意运算符的运算优先级。
【例2.3】布尔运算符的使用。
public class RelationAndConditionOp{ public static void main( String args[] ){ int a = 25,b = 3; boolean d = a < b; // d = false System.out.println("a < b = " + d ); int e = 3; if(e != 0 && a / e > 5)System.out.println( "a / e = " + a / e ); int f = 0; if(f != 0 && a / f > 5) System.out.println("a / f = " + a / f); else System.out.println("f = " + f ); } }
程序运行结果为:
a < b = false a / e = 8 f = 0
熟练地掌握关系运算符和布尔运算符,可以用逻辑表达式描述复杂的条件。
【例2.4】布尔表达式的使用。
(1)用int变量a,b,c表示三个线段的长,它们能构成一个三角形的条件是:任意两边之和大于第三边。该条件的Java布尔表达式为:
(a + b) > c && (b + c) > a && (a + c) > b 或 !((a + b) <= c || (b + c) <= a || (a + c) <= b)
(2)用int变量y,表示年号y是闰年:
y % 400 == 0 | y % 4 == 0 & y % 100 != 0
(3)用int变量age存放年龄,boolean变量sex存放性别(true为男)。表示20岁与25岁之间的女性:
20 <= age & age <= 25 & !sex
2.4.4 位运算符
位运算符用来对二进制位进行运算,运算操作数应是整数类型,结果也是整数类型。Java中提供了表2.11 所示的位运算符。表中前四种称为位逻辑运算符,后三种称为移位运算符。
表2.11 位运算符列表
为了理解位运算符的功能,应掌握运算数据的二进制表示形式。Java使用补码表示二进制数,在补码表示中,最高位为符号位。正数的符号位用0 表示,其余各位代表数值本身。例如,+1的8位补码为00000001。负数的符号位用1表示,通常用将负数的绝对值的补码取反加1的方法来得到负数的补码。例如,-1的8位补码为11111111(-1的绝对值的8位补码00000001按位取反加1为11111110+1=11111111),-42的补码为11010110 (-42的绝对值的8位补码00101010按位取反加1为11010101 + 1 = 11010110 )。
若两个数据长度不同(如short和int型),对它们进行位运算时,则系统首先会将长度短的数据的左侧用符号位填满(称为符号位扩展)。
1.按位取反运算符(~)
按位取反运算符“~”是一元运算符,对数据的各个二进制位取反,即将0 变为1,1变为0。例如:
int a=0x45 , b; b=~a; // b = 0xba
2.按位与运算符(&)
参与运算的两个值,如果两个相应的位都为1,则该位的结果为1,否则为0。例如:
0 & 0 = 0,0 & 1 = 0,1 & 0 = 0,1 & 1 = 1
按位与可以用来把某些特定的位置0(复位),其他位不变。这时只需将要置0 的位同0与,而维持不变的位同1与。例如:
int a = 0x45 , b = 0x31; b = a & b; // b = 1
3.按位或运算符(|)
参与运算的两个值,如果两个相应的位都为0,则该位的结果为0,否则为1。即
0 | 0 = 0,0 | 1 = 1,1 | 0 = 1,1 | 1 = 1
按位或可以用来把某些特定的位置1(置位),而不影响其他位。这时只需将要置1 的位同1或,而维持不变的位同0或。例如:
int a = 0x45 , b = 0x31; b = a | b; // b = 0x75
4.按位异或运算符(^)
参与运算的两个值,如果两个相应的位相同,则该位的结果为0,否则为1。例如:
0 ^ 0 = 0,0 ^ 1 = 1,1 ^ 0 = 1,1 ^ 1 = 0
按位异或也称为按位加,可用于求反某些位。要求求反的位同1 异或,维持不变的位同0异或。这种运算有如下特性:(x^y)^y = x。例如:
int a = 0x45,b = 0x31; b = a ^ b; // b = 0x74
5.左移运算符(<<)
用来将一个数据的所有二进制位全部左移若干位。
在不产生溢出的情况下,数据左移1位相当于乘以2,而且用左移来实现乘法比乘法运算速度要快。例如:
int a = 7 , b; b = a << 1; // b = 14
6.算术右移运算符(>>)
用来将一个数据的所有二进制位全部右移若干位。移出的低位被舍弃,最高位用符号位补入。
右移1位相当于除以2取商,而且用右移来实现除法比除法运算速度要快。例如:
int a = -20 , b; b = a >> 1; // b = -10
但要注意,当移位数据为负且最低位有1 移出时,数据算术右移1 位与数据除以2 的结果不同。例如,-5(0xfb)右移1位等于-3,而(-5)/2的结果是-2。
7.逻辑右移运算符(>>>)
用来将一个数据的所有二进制位全部右移若干位。移出的低位被舍弃,最高位用0 补入。例如:
int a = 0x88 , b; b = a >>> 2; // b = 0x22(34)
2.4.5 赋值运算符
赋值运算符都是二元运算符,具有右结合性。
1.简单赋值运算符(=)
赋值运算符“=”用来将一个数据赋给一个变量。在赋值运算符两侧的类型不一致的情况下,若左侧变量的数据类型的级别高,则右侧的数据被转换为与左侧相同的高级数据类型,然后赋给左侧变量。否则,需要使用强制类型转换运算符。
2.复合赋值运算符
Java语言允许使用复合赋值运算符,即在赋值符前加上其他二元运算符。使用复合赋值运算符可简化表达式的书写。例如:a += 5等价于a = a + 5。复合赋值运算符有11种,见表2.12所示。
表2.12 复合赋值运算符
复合赋值运算符使用比较简单,但要注意下述两点。
(1)复合赋值运算符的右边是一整体,例如:
a *= b + c;
等价于
a = a * (b + c);
而不是
a = a * b + c;
(2)表2.12中的等价是有条件的:即op1仅计算1次。例如:
设有int a[]={1,2},b=2,i=0; // a是一数组
则a[i++] += b; // 执行后i=1
不等价于a[i++]=a[i++] + b; // 执行后i=2
2.4.6 条件运算符
条件运算符是一种三元运算符,它的格式如下:
布尔表达式 ? 表达式1: 表达式2
在这个式子中,先计算布尔表达式的值,若为真,则计算并返回表达式1,若为假,则计算并返回表达式2。例如:
(a > b) ? a : b
这个表达式将返回a和b中较大的那个数值。
2.4.7 字符串运算符
运算符“+”可以实现两个或多个字符串的连接,也可实现字符串与其他类对象的连接,在连接时,其他类对象会被转换成字符串。另外,运算符“+=”把两个字符串连接的结果放进第一个字符串里,在前面的例子里,当想把几项输出内容输出在同一行里时使用的就是“+”运算符。