操作符
Operators
既然你已经学会了如何声明和初始化变量,接下来你可能想知道如何对变量进行操作。学习Java编程语言的运算符是一个很好的起点。运算符是特殊符号,它们对一个、两个或三个操作数执行特定操作,然后返回结果。
在探索Java编程语言的运算符时,提前了解哪些运算符具有最高优先级会对您有所帮助。下表中的运算符按优先级顺序排列。运算符在表格中位置越靠上,其优先级越高。优先级较高的运算符将在优先级相对较低的运算符之前进行求值。同一行中的运算符具有相同优先级。当相同优先级的运算符出现在同一表达式中时,需遵循特定规则确定其计算顺序。除赋值运算符外,所有二元运算符均按从左到右的顺序计算;赋值运算符则按从右到左的顺序计算。
| 操作符 | 优先级 |
|---|---|
| postfix | expr++, expr– |
| unary | ++expr, –expr, +expr, -expr, ~, ! |
| multiplicative | *, /, % |
| additive | +, - |
| shift | <<, >>, >>> |
| relational | <,>,<=,>=,instanceof |
| equality | ==, != |
| bitwise AND | & |
| bitwise exclusive OR | ^ |
| bitwise inclusive OR | | |
| logical AND | && |
| logical OR | || |
| ternary | ? : |
| assignment | =,+=,-=,*=,/=,%=,&=,^=,|=,<<=,>>=,>>>= |
在通用编程中,某些运算符的使用频率往往高于其他运算符;例如赋值运算符 = 的使用远比无符号右移运算符 >>> 更为普遍。基于此,下文将首先聚焦于日常工作中最常用的运算符,最后再探讨那些较少使用的运算符。每项讨论均附有可编译运行的示例代码,通过研究其输出结果,有助于巩固所学知识。
简单赋值运算符
你最常遇到的运算符之一就是简单的赋值运算符 =。你在 Bicycle 类中见过这个运算符;它将右侧的值赋给左侧的操作数:
int cadence = 0;
int speed = 0;
int gear = 1;
该运算符也可用于对象以分配对象引用。
算术运算符
Java编程语言提供了执行加法、减法、乘法和除法的运算符。这些运算符很可能与你在基础数学中接触过的对应运算符相似。唯一可能看起来陌生的符号是%,它表示将一个操作数除以另一个操作数,并返回余数作为结果。
| 操作符 | 描述 |
|---|---|
| + | 加法运算符(也用于字符串连接) |
| - | 减法运算符 |
| * | 乘法运算符 |
| / | 除法运算符 |
| % | 求余运算符 |
以下程序 ArithmeticDemo 用于测试算术运算符。
public class ArithmeticDemo {
public static void main(String[] args) {
int result = 1 + 2;
//result is now 3
IO.println("1 + 2 = " + result);
int original_result = result;
result = result - 1;
// result is now 2
IO.println(original_result + " - 1 = " + result);
original_result = result;
result = result * 2;
// result is now 4
IO.println(original_result + " * 2 = " + result);
original_result = result;
result = result / 2;
// result is now 2
IO.println(original_result + " / 2 = " + result);
original_result = result;
result = result + 8;
// result is now 10
IO.println(original_result + " + 8 = " + result);
original_result = result;
result = result % 7;
// result is now 3
IO.println(original_result + " % 7 = " + result);
}
}
运行该程序将产生以下输出:
1 + 2 = 3
3 - 1 = 2
2 * 2 = 4
4 / 2 = 2
2 + 8 = 10
10 % 7 = 3
您还可以将算术运算符与简单赋值运算符结合使用,形成复合赋值。例如,x += 1; 和 x = x + 1; 都能将变量 x 的值增加 1。
- 运算符也可用于连接(拼接)两个字符串,如下面的ConcatDemo程序所示:
public class ConcatDemo {
public static void main(String[] args) {
String firstString = "This is";
String secondString = " a concatenated string.";
String thirdString = firstString + secondString;
IO.println(thirdString);
}
}
本程序执行完毕时,变量 thirdString 包含字符串 This is a concatenated string.,该字符串将被打印到标准输出。
一元运算符
一元运算符仅需一个操作数;它们执行多种操作,例如将值增减1、取表达式的负值,或反转布尔值的状态。
| 操作符 | 描述 |
|---|---|
| + | 一元加运算符;表示正值(不过数字本身是正的,无需此运算符) |
| - | 一元减运算符;取表达式的负值 |
| ++ | 递增运算符;将值增加1 |
| – | 递减运算符;将值减去1 |
| ! | 逻辑取反运算符;将布尔值取反 |
以下程序 UnaryDemo 用于测试一元运算符:
public class UnaryDemo {
public static void main(String[] args) {
int result = +1;
// result is now 1
IO.println(result);
result--;
// result is now 0
IO.println(result);
result++;
// result is now 1
IO.println(result);
result = -result;
// result is now -1
IO.println(result);
boolean success = false;
// false
IO.println(success);
// true
IO.println(!success);
}
}
增量/减量运算符可置于操作数之前(前缀)或之后(后缀)。代码 result++; 和 ++result; 均会使 result 值增加 1。二者的唯一区别在于:前缀形式(++result)的表达式结果为递增后的值,而后缀形式(result++)的表达式结果为原始值。若仅执行简单递增/递减操作,选择哪种形式并无实质影响。但若在更复杂的表达式中使用该运算符,选择方式可能产生显著差异。
以下程序 PrePostDemo 演示了前缀/后缀一元自增运算符:
public class PrePostDemo {
public static void main(String[] args) {
int i = 3;
i++;
// prints 4
IO.println(i);
++i;
// prints 5
IO.println(i);
// prints 6
IO.println(++i);
// prints 6
IO.println(i++);
// prints 7
IO.println(i);
}
}
等号与关系运算符
等值运算符和关系运算符用于判断一个操作数是否大于、小于、等于或不等于另一个操作数。其中大多数运算符对您来说应该也很熟悉。请注意,在比较两个基本数据类型值是否相等时,必须使用 == 而非 = 。
以下程序 ComparisonDemo 用于测试比较运算符:
public class ComparisonDemo {
public static void main(String[] args) {
int value1 = 1;
int value2 = 2;
if (value1 == value2) {
IO.println("value1 == value2");
}
if (value1 != value2) {
IO.println("value1 != value2");
}
if (value1 > value2) {
IO.println("value1 > value2");
}
if (value1 < value2) {
IO.println("value1 < value2");
}
if (value1 <= value2) {
IO.println("value1 <= value2");
}
}
}
运行此程序将产生以下输出:
value1 != value2
value1 < value2
value1 <= value2
条件运算符
&& 和 || 运算符对两个布尔表达式执行条件与和条件或运算。这些运算符具有”短路”特性,即仅在必要时才会求值第二个操作数。
| 运算符 | 描述 |
|---|---|
| && | 条件与运算 |
| || | 条件或运算 |
以下程序 ConditionalDemo1 测试了这些运算符:
public class ConditionalDemo1 {
public static void main(String[] args) {
int value1 = 1;
int value2 = 2;
if ((value1 == 1) && (value2 == 2)) {
IO.println("value1 is 1 AND value2 is 2");
}
if ((value1 == 1) || (value2 == 1)) {
IO.println("value1 is 1 OR value2 is 1");
}
}
}
另一个条件运算符是 ?:,可视为 if-then-else 语句的简写形式。该运算符因使用三个操作数而被称为三元运算符。在下例中,该运算符应解读为:”若 someCondition 为真,则将 value1 的值赋给 result;否则将 value2 的值赋给 result。”
以下程序 ConditionalDemo2 测试 ?: 运算符:
public class ConditionalDemo2 {
public static void main(String[] args) {
int value1 = 1;
int value2 = 2;
int result;
boolean someConfition = true;
result = someConfition ? value1 : value2;
IO.println(result);
}
}
由于 someCondition 为真,该程序将”1”输出到屏幕。当表达式紧凑且无副作用(如赋值操作)时,使用 ?: 运算符替代 if-then-else 语句可提升代码可读性。
类型比较运算符 instanceof
instanceof 运算符用于将对象与指定类型进行比较。你可以使用它来测试对象是否为某个类的实例、某个子类的实例,或是实现特定接口的类的实例。
以下程序 InstanceofDemo 定义了一个父类(命名为 Parent )、一个简单接口(命名为 MyInterface )以及一个继承自父类并实现该接口的子类(命名为 Child )。
public class InstanceOfDemo {
public static void main(String[] args) {
Parent obj1 = new Parent();
Parent obj2 = new Child();
IO.println("obj1 instanceof Parent: " + (obj1 instanceof Parent));
IO.println("obj1 instanceof Child: " + (obj1 instanceof Child));
IO.println("obj1 instanceof MyInterface: " + (obj1 instanceof MyInterface));
IO.println("obj2 instanceof Parent: " + (obj2 instanceof Parent));
IO.println("obj2 instanceof Child: " + (obj2 instanceof Child));
IO.println("obj2 instanceof MyInterface: " + (obj2 instanceof MyInterface));
}
}
class Parent{}
interface MyInterface{}
class Child extends Parent implements MyInterface{}
上面的程序将产生以下输出:
obj1 instanceof Parent: true
obj1 instanceof Child: false
obj1 instanceof MyInterface: false
obj2 instanceof Parent: true
obj2 instanceof Child: true
obj2 instanceof MyInterface: true
使用 instanceof 运算符时,请注意 null 不是任何类型的实例。
位运算符与位移运算符
Java 编程语言还提供了对整数类型执行位运算和位移运算的运算符。本节讨论的运算符使用频率较低,因此对其介绍较为简略;其目的仅在于让您了解这些运算符的存在。
一元位运算符~可对位模式进行反转;它可应用于任何整数类型,将所有”0”变为”1”,所有”1”变为”0”。例如,一个字节包含8位;对位模式为 00000000 的值应用此运算符后,其模式将变为 11111111 。
带符号左移运算符 << 将位模式向左移位,带符号右移运算符 > 将位模式向右移位。位模式由左操作数指定,移位位数由右操作数决定。无符号右移运算符 >>> 会在最左位移入零,而 > 操作后的最左位取决于符号扩展。
位运算符 & 执行位与运算。
位运算符 ^ 执行位异或运算。
位运算符 | 执行位或运算。
以下程序 BitDemo 使用位与运算符将数字 “2” 输出到标准输出。
public class BitDemo {
public static void main(String[] args) {
int bitmask = 0x000F;
int val = 0x2222;
// prints "2"
IO.println(val & bitmask);
}
}