Java 异常

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编程系列(大部分内容摘自该教程)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值