【Java】异常处理

异常:

        指的是程序运行过程中,因为用户的误操作、代码的BUG等等一系列原因,引起的程序奔溃的现象,被称为异常。

        有一些错误是用户造成的,比如,希望用户输入一个 int 类型的年龄,但是用户的输入是 abc

// 假设用户输入了abc

String s = "abc";

int n = Integer.parseInt(s); // NumberFormatException!

        程序想要读写某个文件的内容,但是用户已经把它删除了: 

// 用户删除了该文件:

String t = readFile("C:\\abc.txt"); // FileNotFoundException! 

         还有一些错误是随机出现,并且永远不可能避免的。

        比如:

  •                    网络突然断了,连接不到远程服务器;
  •                    内存耗尽,程序崩溃了;
  •                    用户点“打印”,但根本没有打印机;
  •                    ……

        所以,一个健壮的程序必须处理各种各样的错误。

        所谓错误,就是程序调用某个函数的时候,如果失败了,就表示出错。

调用方如何获知调用失败的信息?

        Java内置了一套异常处理机制,总是使用异常来表示错误。

        异常是一种 class ,因此它本身带有类型信息。异常可以在任何地方抛出,但只需要在上层捕 获,这样就和方法调用分离了:

try {

         String s = processFile(“C:\\test.txt”);

                // ok:

        } catch (FileNotFoundException e) {

                // file not found:

        } catch (SecurityException e) {

                // no read permission:

        } catch (IOException e) {

                // io error:

        } catch (Exception e) {

                // other error:

}

因为Java的异常是 class ,它的继承关系如下:

         

 从继承关系可知: Throwable 是异常体系的根,它继承自 Object 。 Throwable 有两个体 系: Error Exception Error 表示严重的错误,程序对此一般无能为力,例如:

  •         OutOfMemoryError :内存耗尽
  •         NoClassDefFoundError :无法加载某个Class
  •         StackOverflowError :栈溢出

Exception 则是运行时的错误,它可以被捕获并处理。 某些异常是应用程序逻辑处理的一部分,应该捕获并处理。例如:

  •         NumberFormatException :数值类型的格式错误
  •         FileNotFoundException :未找到文件
  •         SocketException :读取网络失败

还有一些异常是程序逻辑编写不对造成的,应该修复程序本身。例如:

  •         NullPointerException :对某个 null 的对象调用方法或字段
  •         IndexOutOfBoundsException :数组索引越界

Exception 又分为两大类:

         1. RuntimeException 以及它的子类;

         2. 非 RuntimeException (包括 IOException ReflectiveOperationException 等 等)

Java规定:

  •         必须捕获的异常,包括 Exception 及其子类,但不包括 RuntimeException 及其子类,这 种类型的异常称为Checked Exception
  •         不需要捕获的异常,包括 Error 及其子类, RuntimeException 及其子类。
  •        

捕获异常: 

        捕获异常使用 try...catch 语句,把可能发生异常的代码放到 try {...} 中,然后使用 catch 捕获对应的 Exception 及其子类:

try {
    
    } catch(XxxException e) {
        // 异常处理
    } catch(XxxxException e) {
        // 异常处理
    } catch(Exception e) {
        // 异常处理
    } finally {
        // 必须要执行的代码

    }

 Java的 try ... catch 机制提供的 finally 语句, finally 语句块保证有无错误都会执行。

注意 finally 有几个特点:

        1. finally 语句不是必须的,可写可不写;

        2. finally 总是最后执行。

        如果没有发生异常,就正常执行 try { ... } 语句块,然后执行 finally 。如果发生了异常, 就中断执行 try { ... } 语句块,然后跳转执行匹配的 catch 语句块,最后执行 finally

         可见, finally 是用来保证一些代码必须执行的。

捕获多种异常: 

        如果某些异常的处理逻辑相同,但是异常本身不存在继承关系,那么就得编写多条 catch 子句:

public static void main(String[] args) {
    try {
        process1();
        process2();
        process3();
    } catch (IOException e)
    {
        System.out.println("Bad input");
    } catch (NumberFormatException e) {
        System.out.println("Bad input");
    } catch (Exception e) {
        System.out.println("Unknown error");
    }
}

抛出异常:

      异常的传播

        当某个方法抛出了异常时,如果当前方法没有捕获异常,异常就会被抛到上层调用方法,直到遇到 某个 try ... catch 被捕获为止:

public class Main {

        public static void main(String[] args) {

                try {

                         process1();

                } catch (Exception e) {

                        e.printStackTrace();

                 }

        }

static void process1() {

         process2();

}

static void process2() {

         Integer.parseInt(null); // 会抛出NumberFormatException

        }

}

        通过 printStackTrace() 可以打印出方法的调用栈,类似:

java.lang.NumberFormatException:  null

        at java.base/java.lang.Integer.parseInt(Integer.java:614)

        at java.base/java.lang.Integer.parseInt(Integer.java:770)

        at Main.process2(Main.java:16) at Main.process1(Main.java:12)

        at Main.main(Main.java:5) 

        printStackTrace() 对于调试错误非常有用,上述信息表示: NumberFormatException 是在 java.lang.Integer.parseInt 方法中被抛出的,从下往上看,调用层次依次是:

        1. main() 调用 process1() ;

        2. process1() 调用 process2() ;

        3. process2() 调用 Integer.parseInt(String) ;

        4. Integer.parseInt(String) 调用 Integer.parseInt(String, int) 。

抛出异常:

        当发生错误时,例如,用户输入了非法的字符,我们就可以抛出异常。

        如何抛出异常?参考 Integer.parseInt() 方法,抛出异常分两步:

                1. 创建某个 Exception 的实例;

                2. 用 throw 语句抛出。

void process2(String s) {

         if (s==null) {

                NullPointerException e = new NullPointerException();

                 throw e;

        }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值