运算符也称为操作符,用于对数据进行计算和处理以及改变特定对象的值。运算符按照操作数的数目来分类,可以分为一元运算符(如“++”、“--”),二元运算符(如“+”和“<=”)、三元运算符(如“?:”)。运算按照符对数据的操作结果来分类,可以分为算术运算符、关系运算符、逻辑运算符和位运算符。
运算符是进行特定类型运算的符号,下面将对Java语言中的运算符做详细的说明。
算术运算符用在数学表达式中,其用法和功能与数学(或其他计算机语言)中的一样,Java定义了下列算术运算符(见表2-5)。
表2-5 算术运算符及其含义
运 算 符 |
名 称 |
实 例 |
运 算 符 |
名 称 |
实 例 |
+ |
加法 |
a+b |
% |
模运算 |
a%b |
- |
减法(一元减号) |
a-b |
++ |
递增运算 |
a++ |
* |
乘法 |
a*b |
-- |
递减运算 |
B-- |
/ |
除法 |
a/b |
|
|
|
算术运算符的运算数必须是数字类型。算术运算符不能用在布尔类型上,但是可以用在char类型上,因为在Java中,char类型实质上是int类型的一个子集。
关系运算符用于测试两个操作数之间的关系,形成关系表达式。关系表达式将返回一个布尔值。关系运算符常与布尔逻辑运算符一起使用,作为流控制语句的判断条件。Java定义的关系运算符如表2-6所示。
表2-6 关系运算符及其含义
关系运算符 |
名 称 |
实 例 |
关系运算符 |
名 称 |
实 例 |
> |
大于 |
a>b |
<= |
小于等于 |
a<=b |
>= |
大于等于 |
a>=b |
== |
等于 |
a==b |
< |
小于 |
a<b |
!= |
不等于 |
a!=b |
【例2-1】关系运算符的使用。
public class RelationalDemo {
public static void main(String[] args) {
//a few numbers
int i = 37;
int j = 42;
int k = 42;
System.out.println("Variable values...");
System.out.println(" i = " + i);
System.out.println(" j = " + j);
System.out.println(" k = " + k);
//greater than
System.out.println("Greater than...");
System.out.println(" i > j = " + (i > j)); //false
System.out.println(" j > i = " + (j > i)); //true
System.out.println(" k > j = " + (k > j)); //false, they are equal
//greater than or equal to
System.out.println("Greater than or equal to...");
System.out.println(" i >= j = " + (i >= j)); //false
System.out.println(" j >= i = " + (j >= i)); //true
System.out.println(" k >= j = " + (k >= j)); //true
//less than
System.out.println("Less than...");
System.out.println(" i < j = " + (i < j)); //true
System.out.println(" j < i = " + (j < i)); //false
System.out.println(" k < j = " + (k < j)); //false
//less than or equal to
System.out.println("Less than or equal to...");
System.out.println(" i <= j = " + (i <= j)); //true
System.out.println(" j <= i = " + (j <= i)); //false
System.out.println(" k <= j = " + (k <= j)); //true
//equal to
System.out.println("Equal to...");
System.out.println(" i == j = " + (i == j)); //false
System.out.println(" k == j = " + (k == j)); //true
//not equal to
System.out.println("Not equal to...");
System.out.println(" i != j = " + (i != j)); //true
System.out.println(" k != j = " + (k != j)); //false
}
}
这个程序的输出如下:
Variable values…
i = 37
j = 42
k = 42
Greater than…
i > j = false
j > i = true
k > j = false
Greater than or equal to…
i >= j = false
j >= i = true
k >= j = true
Less than…
i < j = true
j < i = false
k < j = false
Less than or equal to…
i <= j = true
j <= i = false
k <= j = true
Equal to…
i == j = false
k == j = true
Not equal to…
i != j = true
k != j = false
逻辑运算符用于进行逻辑运算。逻辑运算符有4个:“&&”、“||”、“!”、“^”,即与、或、非、异或。它们的运算规则如下:
当且仅当两个操作数的值均为true时,“&&”运算的结果才是true,否则都是false。
· 当且仅当两个操作数的值均为false时,“||”运算的结果才是false,否则都是true。
·“!”属于一元运算符,它只对一个自变量进行操作,生成与操作数相反的值。若输入true,则输出false;若输入false,则输出true。
· 仅当两个操作数的值分别为true和false时,“^”运算的结果才是true,否则都是false。
表2-7列出了逻辑运算符,表2-8列出了实例的逻辑运算结果。
表2-7 逻辑运算符及其含义
逻辑运算符 |
名 称 |
实 例 |
逻辑运算符 |
名 称 |
实 例 |
&& |
与(可短路) |
a&&b |
! |
非 |
!a |
|| |
或(可短路) |
a||b |
^ |
异或 |
a^b |
表2-8 逻辑运算结果
A |
B |
A&&B |
A||B |
!A |
A^B |
true |
false |
false |
true |
false |
true |
false |
true |
false |
true |
true |
true |
false |
false |
false |
false |
true |
false |
true |
true |
true |
true |
false |
false |
【例2-2】如何使用关系和逻辑运算符。
import java.util.*;
public class Bool {
public static void main(String[] args) {
Random rand=new Random();
int i=rand.nextInt()%100;
int j=rand.nextInt()%100;
System.out.println ("i="+i);
System.out.println ("j="+j);
System.out.println ("i>j is "+(i>j));
System.out.println ("i<j is "+(i<j));
System.out.println ("i>=j is "+(i>=j));
System.out.println ("i<=j is "+(i<=j));
System.out.println ("i==j is "+(i==j));
System.out.println ("i!=j is "+(i!=j));
System.out.println ("(i<10)&&(j<10) is "+((i<10)&&(j<10)));
System.out.println ("(i<10)||(j<10) is "+((i <10)||(j<10)));
}
}
在Java中只可以将逻辑运算符应用于布尔值。与C和C++不同,Java不可以将一个非布尔值当作布尔值在逻辑表达式中使用。
还要说明的一个问题是“短路”,它是Java进行逻辑运算时所独有的一个特性。
在进行逻辑运算时,只要能明确得出整个表达式为真或为假的结论,就能对整个表达式进行逻辑求值。因此,求解一个逻辑表达式时就有可能不必要对其所有的部分进行求值。
例如,一个逻辑表达式是:
<条件1>&&<条件2>&&<条件3>
在求解过程中,当判断出<条件1>为假时,则整个表达式的值必定为假,不需要再测试<条件2>和<条件3>。事实上,“短路”一词的由来正因于此。
Java语言中的位运算总体来说分为两类:按位运算和移位运算。相应地也就提供了两类运算符:按位运算符和移位运算符。这些运算符只用于整型和字符型数据。
按位运算符允许操作两个整型数据中的单个“比特”,即二进制位。按位运算符会对两个自变量中对应的位执行布尔运算,并最终生成一个结果。由于Java的设计初衷是嵌入电视顶置盒内,所以这种低级操作仍被保留下来。然而,由于操作系统的进步,现在也许不必过于频繁地进行按位运算。
Java中有4种按位操作符,如表2-9所示。
表2-9 按位运算符及其含义
按位运算符 |
名 称 |
实 例 |
按位运算符 |
名 称 |
实 例 |
& |
按位与 |
a&b |
^ |
按位异或 |
a^b |
| |
按位或 |
a|b |
~ |
按位非 |
~a |
若两个输入位都是1,则“按位与”运算符在输出位上生成一个1;否则生成0。若两个输入位里至少有一个是1,则“按位或”运算符在输出位上生成一个1;只有在两个输入位都是0的情况下,它才会生成一个0。若两个输入位的某一个是1,但不全都是1,“按位异或”在输出位上生成一个1;否则生成一个0。“按位非”属于一元运算符;它只对一个自变量进行操作(其他所有运算符都是二元运算符)。“按位非”生成与输入位相反的值,即若输入0,则输出1;若输入1,则输出0。
按位运算符可与等号(=)结合使用,以便合并运算及赋值,如“&=”、“|=”、“^=”都是合法的。
注意:“~”是一元运算符,不可以与等号结合使用。
当操作数为布尔类型时,将boolean类型当作一种“单位”或“单比特”值对待,所以它多少有些独特的地方。此时可执行按位与、按位或和按位异或,但不能执行按位非(避免与逻辑NOT混淆)。对于布尔值,按位运算符具有与逻辑运算符相同的效果,只是它们不会中途“短路”。
有些书中将“&”、“|”、“^”也作为逻辑运算符,在编写程序时一定要注意。
移位运算符面向的运算对象也是二进制的“位”,用来处理整型数据。左移位运算符(<<)能将运算符左边的运算对象向左移动运算符右侧指定的位数(在低位补0)。有符号右移位运算符(>>)则将运算符左边的运算对象向右移动运算符右侧指定的位数。有符号右移位运算符使用了“符号扩展”:若值为正,则在高位插入0;若值为负,则在高位插入1。Java也添加了一种无符号右移位运算符(>>>),它使用了“零扩展”:无论正负,都在高位插入0。这一运算符是C或C++所没有的。
若对char、byte或者short类型的数据进行移位处理,那么在移位进行之前,它们会自动转换成int类型;此时只有右侧的5个低位才会用到,这样可防止在一个子int数里移动不切实际的位数。若对一个long类型的数据进行移位处理,最后得到的结果也是long类型;此时只会用到右侧的6个低位,防止移动超过long类型的数据里现成的位数。但在进行无符号右移位时,也可能遇到一个问题。若对byte或short类型的数据进行右移位运算,则得到的可能不是正确的结果。它们会自动转换成int类型,并进行右移位,但零扩展不会发生,所以在这种情况下会得到-1的结果。另外,移位可与等号结合使用,如“<<=”、“>> =”、“>>> =”都是合法的。此时,运算符左边的变量会移动由右边的值指定的位数,再将得到的结果赋回左边的变量。
【例2-3】移位运算符示例。
public class URShift {
public static void main(String[] args) {
int i=-1;
i>>>=10;
System.out.println(i);
long l=-1;
l>>>=10;
System.out.println(l);
short s=-1;
s>>>=10;
System.out.println(s);
byte b=-1;
b>>>=10;
System.out.println(b);
}
}
在Java语言中,可以用基本的赋值运算符“=”来进行赋值。此外,还提供了几个简单的赋值运算符以同时进行算术运算、移位或按位操作。例如,将一个变量增加一个值并将结果赋值给该变量,一般可以这样使用赋值语句:
i = i + 2;
Java提供了“+=”运算符对上面的赋值语句进行简化,可将其改写为:
i += 2;
表2-10列出了所有的赋值运算符和它们的等价形式。
表2-10 复合赋值运算符
运 算 符 |
用 法 |
等价形式 |
运 算 符 |
用 法 |
等价形式 |
+= |
op1 += op2 |
op1 = op1 + op2 |
|= |
op1 |= op2 |
op1 = op1 | op2 |
-= |
op1 -= op2 |
op1 = op1 - op2 |
^= |
op1 ^= op2 |
op1 = op1 ^ op2 |
*= |
op1 *= op2 |
op1 = op1 * op2 |
<<= |
op1 <<= op2 |
op1 = op1 << op2 |
/= |
op1 /= op2 |
op1 = op1 / op2 |
>>= |
op1 >>= op2 |
op1 = op1 >> op2 |
%= |
op1 %= op2 |
op1 = op1 % op2 |
>>>= |
op1 >>>= op2 |
op1 = op1 >>> op2 |
&= |
op1 &= op2 |
op1 = op1 & op2 |
|
|
|
条件运算符的作用是根据表达式的真假决定变量的值。
条件运算符的一般形式为:
expression?statement1:statement2
expression是返回值为布尔型的表达式,如果这个值为true,那么这个语句返回statement1,否则返回statement2。条件运算符是if…else语句的简略方式。
在编写程序时会遇到很多对象,需要判断某个对象是不是属于某一个特定类,这时就需要使用instanceof运算符。instanceof运算符称为对象引用运算符,当运算符左侧的对象是右侧类的实例时,它将返回true。例如:
public class InstanceOfDemo{
public static void main (String args[]){
InstanceOfDemo t=new InstanceOfDemo();
if( t instanceof InstanceOfDemo ) {
System.out.println("tnInstanceOfDemoXop");
}else{
System.out.println("t`nInstanceOfDemoXop");
}
}
}
在一个表达式中往往存在多个运算符,此时表达式是按照各个运算符的优先级从左到右运算的。也就是说,在一个表达式中,优先级高的运算符首先执行,然后是优先级较低的运算符,对于同优先级的运算符要按照它们的结合性来决定。运算符的结合性决定它们是从左到右计算(左结合性)还是从右到左计算(右结合性)。左结合性很好理解,因为大部分的运算符都是从左到右来计算的。需要注意的是右结合性的运算符,主要有3类:赋值运算符(如“=”、“+=”等)、一元运算符(如“++”、“!”等)和三元运算符(即条件运算符)。运算符具体的优先级顺序如表2-11所示。
表2-11 Java中运算符的优先级
优 先级 |
运 算 符 |
名 称 |
1 |
() |
括号 |
2 |
[ ] |
后缀运算符 |
3 |
-(一元运算符,取负数),!,~,++,―― |
一元运算符 |
4 |
*,/,% |
乘,除,取模 |
5 |
+,- |
加,减 |
6 |
>>,<<,>>> |
移位运算符 |
7 |
>,<,>=,<=,instanceof |
关系运算符 |
8 |
==,!= |
等于,不等于 |
9 |
& |
按位与 |
10 |
^ |
按位异或 |
11 |
| |
按位或 |
12 |
&& |
逻辑与 |
13 |
|| |
逻辑或 |
14 |
?: |
条件运算符 |
15 |
=(包括与“=”结合的运算符,例如:+=) |
赋值运算符 |