JAVA的反常处理结构

反常处理概述

咱们好呀,我是代码小郭,专注JAVA领域常识学习和分享。 我的个人网站地址戳这儿 还在建设中,欢迎来喷。

在日常日子工作中,咱们都会提早想一些预案来防备一些可能会产生的工作,但不论怎么防备,总会呈现一些意料之外的工作,比方最近的水灾,还有火灾,简直防不胜防啊。

反常这个词,就有”未知的意外”的意思。意外呈现了,总得想办法处理吧?假如我不知道该怎么处理,那我应该提交给我的上一级去处理吧?

咱们的程序代码是人的脑力逻辑产品,其实应用程序就等于逻辑+数据。逻辑和数据总该会出问题的,没人能确保自己写的逻辑没有任何缝隙或许产生的数据完全正确啊。

JAVA技术-异常处理框架

因而,在编写程序代码时,编写人员不仅仅要完成正常的逻辑代码,还要考虑逻辑假如出问题了怎么处理,编写人员需求完成针对反常处理带来的额定的工作。

考虑一下,假设咱们编写正常事务逻辑代码是100行,但是反常处理逻辑代码也写了50行,是不是感觉很剩余? 代码复杂度和整洁度肯定受到影响。

那么,反常处理部分的代码是否能够从正常事务逻辑中别离出来呢? 答案是:十分能够!

JAVA言语中给咱们供给了完好的反常处理结构,运用反常处理结构的一个优点是它往往能够下降过错处理代码的复杂度,能够使程序中反常处理代码和正常事务逻辑代码别离,确保程序代码愈加高雅,并提高程序健壮性。假如不运用反常处理,那么就有必要查看特定的过错,并在程序中的许多地方去处理它。而假如运用反常,那就不必在办法调用处进行查看,因为反常机制将确保能够捕获这个过错。

反常处理结构介绍

先看一张图:

JAVA技术-异常处理框架

示例图描绘的便是现在JAVA体系中反常处理结构的整体结构。

java界说了一个Throwable类作为一切反常类的超类。java中界说了许多反常类,首要分为两大类:过错Error和溢出Exception。

从图中能够看出Java界说了一个Throwable类作为一切反常类的超类,还界说了许多子类,子类首要分为两大类:Exception和Error。

  • Exception Exception是程序自身能够有能力处理的一种反常,通常程序员会用trycatch等进行显示的捕获处理。正因为JAVA言语分编译器和运转期,Exception也被规划成了两大类:编译期反常和运转期反常。

1)编译期反常

编译器反常便是CheckedException,一切不是运转期的反常都能够归为此类反常,是指开发人员在编写代码期间查看出来的反常,这种反常强制开发人员有必要在写代码的时分进行处理,不然编译会报错,大大增加了程序的可靠性。

常见的CheckedException有FileNotFoundException、IOException、SQLException、InterruptException等以及咱们自己界说的反常,通常咱们运用的开发工具比方idea就会直接提示这类反常,开发人员有必要自动捕获该类反常,不然编译报错。

示例:

try {
    FileOutputStream fileOutputStream  = new FileOutputStream(new File("F://xxx.dos"));
} catch (FileNotFoundException e) {
    //产生反常时的操作
    e.printStackTrace();
}

::: warning 留意: 只要Java言语供给了Checked反常,其他言语都没有供给Checked反常。Java以为Checked反常都是能够被处理(修正)的反常,所以Java程序有必要显式处理Checked反常。假如程序没有处理Checked反常,该程序在编译时就会产生过错,无法经过编译。 :::

2)运转期反常 运转期反常指的是程序在运转过程中动态产生的各类反常,可能是因为某种事务场景才会触发,非必现。

这类反常一般是程序员编写的代码存在逻辑缝隙而产生,在编写程序时,并不要求有必要运用反常处理机制处理这类反常。

常见的运转期反常有空指针NullPointException、下标越界IndexOutBoundsException、类型转换ClassCastException等。

示例:

int a = 10/0;
  • Error Error是指一些十分严峻的问题,咱们的应用程序自身现已无法修正这些过错,一般是指与虚拟机JVM相关的问题,如系统崩溃、虚拟机过错、动态链接失利等,这种过错无法康复或不行能捕获,将导致应用程序中断。

当机器资源缺乏、或是程序无法持续运转的条件产生时,就产生Error(过错),标明JVM现已处于不行康复的崩溃状况。

大多数过错与代码编写者履行的操作无关,而表明代码运转时JVM呈现的问题,常见的过错有内存溢出OutOfMemoryError、堆栈溢出StackOverFlowError等,这些反常产生时,JVM一般会选则停止程序进程的运转。

总结一下Exception和Error的差异: Error通常是灾难性的丧命的过错,是程序无法控制和处理的,当呈现这些反常时,Java虚拟机(JVM)一般会挑选停止线程;Exception通常情况下是能够被程序处理的,并且在程序中应该尽可能的去处理这些反常。

反常处理关键字

  • try:用于监听。try后紧跟一个花括号括起来的代码块(花括号不行省掉),简称try块,它里面放置可能引发反常的代码,当try句子块内产生反常时,反常就被抛出。
  • catch: 用于捕获反常。catch后对应反常类型和一个代码块,用于处理try块产生对应类型的反常。
  • throws:用在办法签名中,用于声明该办法可能抛出的反常。
  • throw:用于抛出一个实际的反常。throw能够单独作为句子运用,抛出一个具体的反常目标。【抛出反常】
  • finally:用于整理资源,finally句子块总是会被履行。 多个catch块后还能够跟一个finally块,finally块用于收回在try块里翻开的物理资源(如数据库衔接、网络衔接和磁盘文件)。只要finally块履行完成之后,才会回来履行try或许catch块中的return或许throw句子,假如finally中运用了return或许throw等停止办法的句子,则就不会跳回履行,直接停止。

代码示例

运用try…catch处理反常

语法格式:

try{
    //事务代码逻辑
    ...
 }catch(Exception e){
   //反常处理代码
   ...
 }

实例:

public class ExceptionTest {
    public static void main(String[] args) {
        try {
            int a=Integer.parseInt(args[0]);
            int b=Integer.parseInt(args[1]);
            int c=a/b;
            System.out.println("您输入的两个数相除的结果是"+c);
        }catch(IndexOutOfBoundsException e) {
            System.out.println("数组越界,运转时参数不行");
        }catch(NumberFormatException e) {
            System.out.println("数字格式反常");
        }catch(ArithmeticException e) {
            System.out.println("算术反常");
        }catch(Exception e) {
            System.out.println("未知反常");
        }
    }
}

运用throw抛出反常

public class ExceptionTest {
    public static void main(String[] args) {
        try {
            int a=Integer.parseInt("a");
            int b=Integer.parseInt("2");
            int c=a/b;
        }catch(IndexOutOfBoundsException e) {
            throw new RuntimeException("throw抛出反常了");
        }
    }
}

运用throws声明反常

public class ExceptionTest {
    public static void main(String[] args) throws InterruptedException {
        Thread.sleep(1000);
    }
}

运用finally确保最终操作

有些时分,程序在try块里翻开了一些物理资源(例如数据库衔接、网络衔接和磁盘文件),不论 产生反常仍是正常履行完后,这些物理资源都有必要显示收回。 java的反常体系给咱们供给了finally机制,让咱们能够在反常产生时自动完成一些工作,比方进行物理资源的收回。

语法结构:

try{
    //事务完成代码
    ...
  }catch(xxxException e){
    //反常处理块
    ...
  }finally{
     //资源收回
     ...
  }

示例:

public class ExceptionTest {
    public static void main(String[] args) throws Exception {
        try {
            int c=10/0
        }catch(Exception e) {
            System.out.println("产生反常");
        }finally {
            System.out.println("资源收回");
        }
    }
}

怎么访问反常信息

一切的反常目标类中都有如下几个常用办法:

getStackTrace():回来该反常的跟踪栈信息。

printStackTrace():将该反常的跟踪栈信息输出到规范过错输出。

printStackTrace(PrintStream s):将该反常的跟踪栈信息输出到指定输出流。

getMessage():回来该反常信息的跟踪栈信息输出到规范过错输出

自界说反常

有时分JAVA中现已界说好的反常类型不满足现在事务的运用,或许咱们需求针对不同的事务制定不同的事务反常分类,方便过后计算和监控

JAVA的反常结构支撑咱们自界说一个反常类型,自界说类型都需求继承RuntimeException。

下面是一个简略的案例。

完成步骤:

  • 1)声明一个自界说反常类,继承RuntimeException
public class MyException extends RuntimeException{
}
  • 2)编写两个结构器,一个空的,一个有参数的结构器(带给父类的message属性赋值的结构器)
public class MyException extends RuntimeException{
    MyException(){super();}
    MyException(String message){
        super(message);
    }
}
  • 3)在事务代码中运用自界说反常
public class ExceptionTest {
    public static void main(String[] args) throws InterruptedException {
        try {
            //事务代码
            int a = 10/0;
        } catch (Exception e) {
            //捕获系统反常并抛出自界说反常
            throw new MyException("我是自界说反常");
        }
    }
}

总结

反常机制使代码的阅读、编写和调试工作愈加井井有条。

JAVA技术-异常处理框架