java 异常
1.java异常处理基础
异常:发生于程序执行期间,表明出现非法运行状态
异常处理目的:提供不同的错误应对策略和手段,使程序更加稳定安全,让程序在异常的情况下能继续运行下去,不致崩溃。
异常捕获基本语句:
try{
//可能发生错误的代码块
}catch(异常类型 异常对象引用){
//处理异常代码
}finally{
//善后代码
}
Java所有可捕获异常都派生自Exception类
异常处理过程:
1.可能发生错误的代码在try语句块中运行
2.程序检测出错误,抛出一个异常对象,由try语句块跳转到catch语句块,然后catch语句块中代码处理错误
3.不管是否发生异常,finally语句块中代码都被执行
4.如果没有合适异常处理代码,JVM会结束掉整个应用程序
与异常相关的类:
Throwable类有两个子类:
- Exception:出现问题可捕获
- Error:系统错误,由JVM处理
可捕获异常又可以分为两类:
- check异常:直接派生自Exception异常类,必须被捕获或者再次声明抛出
- runtime异常:派生自RuntimeException的异常类,使用throw语句可以随时抛出这种异常对象
异常多态性:
- 可以有多个catch语句块,每个代码块捕获一种异常。在某个try块后有两个不同的catch 块捕获两个相同类型的异常是语法错误。
- 使用catch语句,只能捕获Exception类及其子类的对象。因此,一个捕获Exception对象的catch 语句块可以捕获所有“可捕获”的异常。 (有时候对异常类型不关心时直接catch一个Exception)
- 将catch(Exception e)放在别的catch块前面会使这些catch块都不执行,因此Java不会编译这个程序
java7特性自动释放资源:
try(ClassName obj=new ClassName()){
}catch(Exception e){
//
}
要求ClassName类实现AutoCloseable接口,这样无需在finally子句中调用close方法,如Socket,FileStream等
多层异常捕获:
public class TestMain {
public static void main(String[] args) {
try{
try{
throw new ArrayIndexOutOfBoundsException();
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("ArrayIndexOutOfBoundsException "+"/ 内层try-catch");
}
throw new ArithmeticException();
}catch(ArithmeticException e){
System.out.println("ArithmeticException");
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("ArrayIndexOutOfBoundsException "+"/ 外层try-catch");
}
}
}
输出:
ArrayIndexOutOfBoundsException / 内层try-catch
ArithmeticException
可以发现当嵌套多层try-catch时,异常首先在最接近他的catch语句块中处理
public class TestMain {
public static void main(String[] args) {
try{
try{
throw new ArrayIndexOutOfBoundsException();
}catch(ArithmeticException e){
System.out.println("ArrayIndexOutOfBoundsException "+"/ 内层try-catch");
}
throw new ArithmeticException();
}catch(ArithmeticException e){
System.out.println("ArithmeticException");
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("ArrayIndexOutOfBoundsException "+"/ 外层try-catch");
}
}
}
输出:
ArrayIndexOutOfBoundsException / 外层try-catch
稍微修改代码,可以发现,异常首先发生在内层try-catch,但内层catch并没有捕获该异常的类,因而跳转至外层catch,所以throw new ArithmeticException();不会发生。
之后,如果有finally语句,那么finally语句从内至外依次执行,当有System.exit(0),时finally不会执行,所以finally语句块不一定会执行。
printStackTrace()和getMessage()方法:
public class TestMain {
public static void main(String[] args) {
try{
throw new Exception("Exception is thrown in main");
}
catch(Exception e)
{
e.printStackTrace();
System.out.println(e.getMessage());
}
}
}
输出:
java.lang.Exception: Exception is thrown in main
at learning.TestMain.main(TestMain.java:6)
Exception is thrown in main
- printStackTrace():打印方法调用堆栈
- getMessage():每个Throwable类的对象都有一个getMessage方法,它返回一个字串,这个字串是在Exception构造函数中传入的,通常让这一字串 包含特定异常的相关信息。
2.受控异常
受控异常:checked exception,这类异常必须写try-catch或throw抛出,否则编译不通。通常直接派生自Exception类
throw语句表明某方法中可能出现异常,但他自己不能处理,需要调用者自己处理,当一个方法包含throws子句时,调用此方法必须在代码中使用try-catch进行捕获,或者重新声明,否则编译报错。
RuntimeException(其基类为Exception)和 Error(基类为Throwable)称为非受控的异常。这种异常不用在throws语句中声明。
下面用例对比二者:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class TestMain {
public static void main(String[] args) {
try {
BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));//抛出受控的异常
System.out.print("请输入整数: ");
int input = Integer.parseInt(buf.readLine()); //有可能引发运行时异常
System.out.println("input x 10 = " + (input*10));
}
//以下异常处理语句块是必须的,否则无法通过编译
catch(IOException e) { //受控异常
System.out.println("I/O错误");
}
//以下异常处理语句块可以省略,不影响编译,但在运行时可能出错(比如输入'a')
catch(NumberFormatException e) { //运行时异常
System.out.println("输入必须为整数");
}
}
}
以下代码是抛出多个受控异常方法:
public class TestMain {
public static void main(String[] args) {
try {
throwsTest();
} catch(ArithmeticException e){
System.out.println("捕捉异常");
}
}
private static void throwsTest() throws ArithmeticException,ArrayIndexOutOfBoundsException {
System.out.println("这只是一个测试");
// 程序处理过程假设发生异常
throw new ArithmeticException();
//throw new ArithmeticException();
}
}
catch其中一个异常编译即可通过。
子类抛出受控异常限制:一个子类的throws子句抛出的异常,不能是其基类同名方法抛出的异常对象的父类。
Java7新特性:允许一个catch块捕捉多个异常
catch (SocketException | SecurityException | NullPointerException e){
//exception handler
}
3.自定义异常
自定义异常:
class MyException extends Exception{
}
在合适的地方使用自定义异常对象:
class MyClass{
void someMethod(){
if(条件) throw new MyException();
}
}
参考:
金旭亮Java编程系列(大部分内容摘自该教程)