1.异常处理对性能的影响
一般来说,在Java程序中使用try…catch语句不会对应用的性能造成很大的影响。仅仅当异常发生时,Java虚拟机需要执行额外的操作,来定位处理异常的代码块,这是会对性能产生负面影响。如果抛出异常的代码块和捕获异常的代码块位于同一个方法中,这种影响就会小一些;如果Java虚拟机必须搜索方法调用栈来寻找异常处理代码块,对性能的影响就比较大了。尤其当异常处理代码块位于调用栈的底部时,Java虚拟机定位异常处理代码块就需要大量的工作。
2.运用Java异常处理机制
- 在Java语言中,用try…catch语句来捕获异常。
- finally语句:任何情况下都必须执行的代码
- throws子句:声明可能会出现的异常。如果一个方法可能会出现异常,但没有能力处理这种异常,可以在方法声明处用throws子句来声明跑出异常。
- throw语句:抛出异常
例如:汽车在运行时可能会出现故障,汽车本身没办法处理这个故障,因此Car类的run方法声明抛出异常 CarWrongExcepiton:
public void run() throws CarWrongException {
if(车子无法刹车)
throw new CarWrongException("车子无法刹车");
if(发动机无法启动)
throw new CarWrongException("发动机无法启动");
}
异常处理语句的语法规则
- try代码块不能脱离catch代码块或finally代码块而单独存在。try代码块后面至少有一个catch代码块或finally代码块
- try代码块后面可以有零个或多个catch代码块,还可以有零个或至多一个finally代码块。如果catch代码块和finally代码块并存,finally代码块必须在catch代码块后面
- try代码块后面可以只跟finally代码块
try {
int a = 1;
Thread.sleep(1000);
} catch (Exception e) {
// TODO: handle exception
a--; //编译错误
} finally {
a ++; //编译错误
}
- 如果一个方法可能出现受检查异常,要么用try…catch语句捕获,要么用throws子句声明将它抛出,否则会导致编译错误
- throw语句后面不允许紧跟其它语句,因为这些语句永远不会被执行。例:
try {
int a = 1;
Thread.sleep(1000);
} catch (Exception e) {
// TODO: handle exception
throw e;
a --;
}
异常流程的运行过程
- finally语句不被执行的唯一情况是先执行了用于终止程序的System.exit()方法。exit方法的参数表示程序终止时的状态码,按照编程惯例,0表示正常终止,非0表示异常终止。
正常流程:
try {
System.out.println("Beginning ......");
} finally {
System.out.println("Finally ......");
}
正常输出结果:
Beginning ......
Finally ......
使用exit方法后代码:
try {
System.out.println("Beginning ......");
System.exit(0);
} finally {
System.out.println("Finally ......");
}
输出结果:
Beginning ......
- return语句用于退出本方法。在还行try或catch代码块中的return语句是,加入有finally代码块,会先执行finally代码块。
例:
try {
Object ob = null;
ob.equals("name");
System.out.println("Beginning ......");
return;
} catch (Exception e) {
System.out.println("catch exception ......");
return;
} finally {
System.out.println("finally is ......");
}
运行结果如下:
catch exception ......
finally is ......
- finally代码块虽然在return语句之前被执行,但finally代码块不能通过重新给变量赋值的方式来改变return语句的返回值。
例:
public static void main(String[] args) {
System.out.println("get value is : " + test());
}
public static int test() {
int a = 10;
try {
System.out.println("Beginning ......");
return a;
} finally {
System.out.println("finally is ......");
a = -10;
}
}
运行结果如下:
Beginning ......
finally is ......
get value is : 10
- 建议不要在finally代码块中使用return语句,因为它会导致以下两种潜在的错误。第一种错误是覆盖try或catch代码块中的return语句,如下例所示:
public static void main(String[] args) {
System.out.println("get value is : " + test());
}
public static int test() {
int a = 10;
try {
System.out.println("Beginning ......");
return a;
} finally {
System.out.println("finally is ......");
a = -10;
return a;
}
}
运行结果为(预期应该返回10,但是被finally中的return语句覆盖了):
Beginning ......
finally is ......
get value is : -10
- 第二种错误是丢失异常,如下例所示:
public class ExLoss {
class SpecialException extends Exception {
public SpecialException(String resean) {
System.out.println("get exception is : " + resean);
}
}
public int methodA(int money) throws SpecialException{
if (--money <= 0) {
throw new SpecialException("out of money");
}
return money;
}
public int methodB(int money) throws Exception {
try {
return methodA(money);
} catch (SpecialException e) {
throw new SpecialException("wrong");
} finally {
return 100;
}
}
}
public class HelloWorld {
public static void main(String[] args) {
try {
System.out.println(new ExLoss().methodB(0));
System.out.println("No Exception");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
运行结果如下(没有返回异常,与预期不一致):
get exception is : out of money
100
No Exception
分析说明:methodB()方法的catch代码块继续抛出异常,按理说main()方法的catch代码块应该捕获并处理该异常,但由于methodB()方法的finally代码块有返回值,异常被丢失了,main()方法没有捕获到methodB()方法的异常
-