Java运算符与异常处理详解
立即解锁
发布时间: 2025-08-18 02:21:30 阅读量: 2 订阅数: 15 

### Java 运算符与异常处理详解
#### 1. 运算符的结合性
运算符的结合性决定了在复杂运算符表达式中,当有两个或更多具有相同优先级的运算符时,操作执行的顺序。在给定优先级的所有运算符都具有相同的结合性,要么是左结合,要么是右结合。最高和最低优先级的运算符都是右结合的,包括所有一元运算符、条件运算符和所有赋值运算符。中间的十个二元运算符都是左结合的,这很方便,否则就需要记住它们的优先级和结合性。
例如,对于表达式 `a + b - c`,由于加法和减法运算符具有相同的优先级且是左结合的,计算机将其计算为 `(a + b) - c`。
一元运算符的组合有一些限制:
- 递增或递减运算符的操作数必须是变量。因此,在前置递增或递减运算符与变量名之间不能有其他一元运算符。例如,`+++` 和 `---` 是不允许的,因为解析器会将它们分别解释为前置递增运算符后跟一元加运算符和前置递减运算符后跟一元减运算符。
- 对于任何给定的一元表达式,只能使用一个前置递增运算符、前置递减运算符、后置递增运算符或后置递减运算符。例如,`--x++` 会被计算为 `--(x++)`,但 `x++` 的结果是一个值,不是变量,所以会出错。
以下是包含多个一元运算符的表达式示例:
```java
x = ~a--;
x = -++a;
x = -+~a++;
```
这些示例都可以编译,但这样的复合一元表达式不能用于表达式语句,例如:
```java
~a--; //COMPILER ERROR
-++a; //COMPILER ERROR
+-~a++; //COMPILER ERROR
```
数值比较和相等运算符有时被描述为非结合的。从技术上讲,它们是左结合的,但实际上用处不大。例如,关系表达式 `a < b > c` 无法编译,因为数值比较运算符的操作数必须是基本数值类型。相等表达式也有类似问题,如 `if (a == b == c)` 这样的表达式即使能编译,也基本没有用处。
#### 2. 无损运算符
移位操作被认为是无损的,即计算移位表达式后,左操作数的值不变。例如:
```java
int a = 1;
int b = a << 1;
int c = b << 1;
System.out.println(a);
System.out.println(b);
System.out.println(c);
```
输出结果为:
```
1
2
4
```
如果要同时移位并存储变量的值,可以使用三个复合赋值运算符 `<<=`、`>>=` 或 `>>>=`。
除了递增和递减运算符外,计算一元表达式前后变量的值相同,这些一元运算符也可以用无损来描述。例如:
```java
int a = 25;
int b = 25;
int c = 25;
boolean d = true;
int x;
boolean y;
x = +a;
x = -b;
x = ~c;
y = !d;
if (a == 25 && b == 25 && c == 25 && d == true)
System.out.println("this message does print");
```
#### 3. 异常的精确性
异常在方法或构造函数体中抛出。在变量初始化器、初始化块和构造函数的情况下,异常在特殊初始化方法体中抛出。方法在抛出异常的精确点(起源点)突然结束。如 JLS 所述:异常是精确的,当控制转移发生时,在抛出异常的点之前执行的语句和计算的表达式的所有效果都必须显示已经发生,而在该点之后的表达式、语句或其部分都不能显示已经计算。
例如,以下代码:
```java
class Test {
static {System.out.println("loading program");} // <clinit>
public static void main(String[] args) {
System.out.println("main");
System.out.println("invoking a()");
a();
System.out.println( "end of program");
}
static void a() {
System.out.println("invoking b() in a try-finally");
try {
b();
}
finally {
System.out.println("finally blocks are always executed");
System.out.println("STACK TRACE TO FOLLOW…");
}
}
static void b() {
System.out.println("invoking c()");
c();
}
static void c() {
int i = 0;
System.out.println("ABOUT TO DIVIDE AN INTEGER BY ZERO");
i /= 0;
System.out.println("exceptions are precise");
}
}
```
执行该程序时,输出结果显示在抛出异常后,控制立即转移,`"exceptions are precise"` 和 `"end of program"` 不会打印。
异常精确性规则有两个例外:
- 可能抛出 `NullPointerException` 的表达式只有在所有子表达式都完全计算后才会抛出该异常。例如:
```java
class Test {
static String s;
public static void main(String[] args) {
try {
s.equals(s = "abc");
}
catch(Exception e) {
System.out.println(e);
System.out.print("s = " + s);
}
}
}
```
执行该程序会先计算 `s = "abc"`,然后抛出 `NullPointerException`。
- 当从简单赋值语句的左操作数抛出 `ArrayIndexOutOfBoundsException` 时,该异常会在右操作数计算后才抛出。例如:
```java
class Test {
public static void main(String[] args) {
String[] strings = new String[10];
String s = null;
strings[99] = printSomething();
}
static String printSomething() {
System.out.println("ArrayI
```
0
0
复制全文


