跳至主要內容

异常捕获与处理

wangdx大约 6 分钟

异常捕获与处理

异常处理

在程序中为了保证出现了异常之后可以正确的执行完毕,就需要进行合理的异常处理而对于异常处理主要是通过:try、catch、finally 三个关键字来实现的,首先观察一下异常的处理语法结构:

try{
  //有可能异常代码
}[catch(异常类型 异常对象){
  //异常处理
}catch(异常类型 异常对象){
  //异常处理
}...][finally{
  //最终执行代码
}]
案例
public class Test {
    /*
     * 异常简单实例
     * */
    public static void main(String[] args) {
        try {
            int result = 10 / 0;
            System.out.println("result=" + result);
        }catch (ArithmeticException e){
            //在进行异常处理,如果直接输出对象,所获取信息不完整
            e.printStackTrace();
        }
        System.out.println("大国精神www.daguo.com");
    }
}

java.lang.ArithmeticException: / by zero
	at com.yix/exception.w01.Test.main(Test.java:12)
大国精神www.daguo.com
class Test1 {
    /*
    * try...catch...finally
    * */
    public static void main(String[] args) {
        try {
            int result = 10 / 0;
            System.out.println("result=" + result);
        } catch (ArithmeticException e) {
            e.printStackTrace();
        } finally {
            System.out.println("异常不异常都来执行");
        }
        System.out.println("大国精神www.daguo.com");
    }
}

Connected to the target VM, address: '127.0.0.1:51444', transport: 'socket'
java.lang.ArithmeticException: / by zero
	at com.yix/exception.w01.Test1.main(Test.java:28)
异常不异常都来执行
大国精神www.daguo.com

处理多个异常

现在要通过初始化参数设置两个数学计算的数字,由于初始化参数类型为 String 字符串,这样在程序执行时首先要进行字符串转型,随后才可以实现除法计算,而在这一操作中有可能会存在有三个异常。

  • ArrayIndexOutOfBoundsException 异常:执行时没有输入初始化参数所产生的数组越界异常
  • NumberFormatException 异常:输入的初始化参数不是数字,则转型时出现数字格式化异常;
  • ArithmeticException 异常:在进行数学计算时,被除数为 0,所出现的数学异常。
案例
class Test2 {
    /*
     * 多个异常处理
     * */
    public static void main(String[] args) {
        try {     //将多个可能产生异常放在try中
            int x = Integer.parseInt(args[0]);
            int y = Integer.parseInt(args[1]);
            int result = x / y;
            System.out.println("result = " + result);
        } catch (ArithmeticException e) {
            e.printStackTrace();
        }catch (ArrayIndexOutOfBoundsException e) {
            e.printStackTrace();
        }catch (NumberFormatException e) {
            e.printStackTrace();
        } finally {
            System.out.println("异常否都执行");
        }
        System.out.println("一祥集团:www.yix.com");
    }
}

java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
	at com.yix/exception.w01.Test2.main(Test.java:45)
异常否都执行
一祥集团:www.yix.com

java.lang.NumberFormatException: For input string: "你好"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.base/java.lang.Integer.parseInt(Integer.java:652)
	at java.base/java.lang.Integer.parseInt(Integer.java:770)
	at com.yix/exception.w01.Test2.main(Test.java:46)
异常否都执行
一祥集团:www.yix.com

java.lang.ArithmeticException: / by zero
	at com.yix/exception.w01.Test2.main(Test.java:47)
异常否都执行
一祥集团:www.yix.com

异常处理流程

在程序的开发中会存在有大量的异常类型,如果每一个程序都通过一系列的 catch 进行异常捕获,则对于代码的开发难度实在是太大了,所以要想进行合理的异常处理,那么首先就要掌握异常的处理流程,在分析异常的处理流程之前先观察之前接触过的"ArithmeticException","NumberFormatException”两个异常类的继承结构,

Error 和 Exception

所有的异常类实际上都属于 Throwable 的子类,而在 Throwable 类中实际上会存在有两种子类 Error、Exception

  • Error:JVM 错误,此类错误一般都是发生在 IM 运行的过程之中,并且无法通过程序处理;
  • Exception:程序执行中产生的异常,用户可以处理,程序中接触的异常均为 Exception 子类。

异常处理流程

  • 在程序代码编写过程之中,由于处理逻辑的不到位,那么可能会让代码产生异常,例如“1/0”,而如果代码中添加合适的判断就可以保证不出现此异常。
  • 当异常产生之后会由 JVM 根据异常的类型而自动的实例化一个指定异常类型的异常类对象(控制异常对象的个数对性能提升非常有必要);
  • 如果当前的程序代码之中已经明确的提供了异常处理语句的格式,那么就对异常进行捕获,如果没有提供异常处理语句,那么自动将此异常对象交由 JVM 进行默认的处理,而默认的处理方式为:输出异常信息,同时中断程序的执行;
  • 如果此时的代码中存在有异常处理机构,则会通过 try 语句捕获当前的异常类的实例化对象,同时对于异常产生之后的代码将不再继续执行;
  • 如果在 try 语句之后定义有 catch 语句,那么会自动利用捕获到的实例化对象与 catch 中捕获的异常类型进行匹配,如果匹配成功则使用当前的 catch 进行异常处理,如果匹配不成功,则交由下一个的 catch 继续匹配;
  • 不管是否存在有匹配的 catch 的异常类型,最终都要执行 finally 中的代码,但是如果已经处理过异常则可以继续向下执行其他的操作代码,而如果没有处理过的异常,那么就表示当前的异常处理结构无法处理此异常,则会交 JVm 进行默认处理。
try{

}catch(Exception e){
  e,printStackTrace();
}

throws 关键字

案例
class MyMath{
  public static int div(int x,int y)throws Exception{
    return x/y;
  }
}

class Test{
  public static void main(String[] args){
    try{
      System.out.println(MyMath.div(10,2));
    }catch(Exception e){
      e.printStackTrace();
    }
  }
}

throw 关键字

案例
class MyMath{
  public static int div(int x,int y) throws Exception{
    if(y == 0){
      throw new ArithmeticException("除数不可以为0!!!");
    }
    return x/y;
  }
}

class Test{
  public static void main(String[] args) throws Exception{
      System.out.println(MyMath.div(10,2));
  }
}

RuntimeException

  • 在 Java 里面为了方便用户代码的编写,专门提供了一种 RuntimeException 类,这种异常类的最大特征在于:程序在编译的时候不会强制性的要求用户处理异常,用户可以根据自己的需要选择性进行处理,但是如果没有处理又发生了异常了,将交给 JVM 默认处理。也就是说 RuntimeException 的子异常类,可以由用户根据需要选择性进行处理。
  • 如果要进行字符串转变为 int 数据类型,那么可以利用 Integer 类进行处理,因为在 Integer 类定义了如下方法:
    • 字符串转换 int:public static int parselnt(String s)throws NumberFormatException;
    • 此时 parselnt()方法上抛出了一个 NumberFormatException,而这个异常类就属于 RuntimeException 子类

自定义异常类

  • 如果说现在要模拟一个吃饭的业务,那么就有可能产生有两种异常
    • HugryException:长时间未吃饭,所以会引发一种饥饿异常;
    • ExplodeException:肚子吃到饱。
  • 如果要想进行自定义异常类只需要继承 Exception 或者继承 RuntimeException 的父类即可,千万不要去直接继承 Throwable,因为 Throwable 所描述的范围实在是太广泛了,这样会造成异常类的定义模糊。
案例

assert 关键字

assert 关键字是在 JDK 1.4 的时候正式引入到 Java 中的关键字,其主要的目的是实现断言的功能,所谓的断言是对程序执行的一种推断,当某些语句执行之后结果一定是某个具体的内容。

案例
上次编辑于: