ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java学习之==>异常体系

2019-09-12 13:00:43  阅读:227  来源: 互联网

标签:体系 Java void demo01 static catch 异常 public


一、定义

程序运行时总是会遇到各种各样的问题,Java中的异常体系就是针对这些问题提出的统一的处理方案。在Java中,将这些各种各样的问题进行归类后,统一称为异常。

二、分类

我们先来看看下面这个图:

  • 错误(Error)
    • 虚拟机错误(VirtualMachineError),如:资源耗尽、内存溢出;
  • 异常(Exception)
    • 运行时异常(RuntimeException)
    • 受检异常(Checked Exception)

  由上图可以看出来,Java的异常体系由 Throwable 类作为超类,两个直接子类是 Error 类和 Exception 类分别标错错误和异常。其中,异常又包括运行时异常(RuntimeException)和受检异常(Checked Exception),下面将介绍这些错误和异常的区别:

1、错误(Error)和异常(Exception)

  Error 是程序无法处理的错误,它是由Java虚拟机(JVM)产生和抛出的,比如:OutOfMemoryError、ThreadDeath等。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。

  Exception 是程序本身可以处理的异常,这种异常分两大类,运行时异常和受检异常,程序中可以处理这些异常。

2、运行时异常(RuntimeException)和受检异常(Checked Exception)

  运行时异常都是RuntimeException类及其子类异常,如NullPointerException、IndexOutOfBoundsException等,此类异常属于不可查异常,一般是由程序逻辑错误引起的,在程序中可以选择捕获处理,也可以不处理。

  受检异常是除RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等,在程序中,通常不会自定义该类异常,而是直接使用系统提供的异常类。

三、异常的处理

1、受检异常

通常,我们在处理受检异常时有三种方式:

第一种:在方法名后面使用关键字throws抛出异常,同时在调用该方法时需要使用try..catch来处理该异常

public class App {

  public static void main(String[] args) {

    try {
      demo01();
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }
  }

  private static void demo01() throws FileNotFoundException {

    new FileInputStream(new File("test.log"));

  }
}

第二种:直接使用try..catch处理,自己抛出,自己处理,没啥意义

public class App {

  public static void main(String[] args) {

    demo01();
  }

  private static void demo01() {

    try {
      new FileInputStream(new File("test.log"));
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }
  }
}

第三种:使用try..catch,在try里面把异常声明出来,然后再catch

public class App {

  public static void main(String[] args) {

    demo01();
  }

  private static void demo01() {
    try (FileInputStream inputStream = new FileInputStream(new File("test.log"))) {
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

运行结果如下:

2、运行时异常

在编译时,运行时异常不会被发现,所以不要要求在代码中一定要处理这些异常。但是,如果程序员愿意,也可以使用 try...catch...finally 来处理这些异常。对于这些异常,发生的原因多半是代码写的有问题,我们应该修正代码,而不是去通过异常处理器处理。

public class App {

  public static void main(String[] args) {

    demo01(0);
  }

  private static void demo01(Integer num) {

    if (num == 0) {
      throw new ArithmeticException("分母不能为0");
    }
    
    int result = 1024/num;
  }
}

上面这种情况,如果没有 if() 代码,程序在运行过程中会抛出异常中断程序,虽然我们增加了 if() 代码块主动抛出了异常增加了异常的可读性,但是程序仍然会中断。正确的处理方式是我们可以在 if() 代码块下进行一些其他逻辑的处理,从而程序不会走到除法分支,从而不会报错。这就是上面所说的,运行时异常,我们通常需要去优化代码逻辑,而不是处理异常。

public class App {

  public static void main(String[] args) {

    demo01(0);
  }

  private static void demo01(Integer num) {

    try {
      int result = 1024/num;
    }catch (ArithmeticException e) {
      e.printStackTrace();
    }finally {
      System.out.println("处理完毕");
    }
  }
}

这种情况是使用 try...catch...finally 捕获异常再进行处理。

四、异常处理流程

public class App {

  public static void main(String[] args) {

    demo01(0);
    System.out.println("-------------");
    demo01(1);
  }

  private static int demo01(Integer num) {
    try {
      // 这里是正常的业务代码,要被我处理的代码,
      System.out.println("AAA");
      int result = 1024 / num;
      System.out.println("BBB");
      return result;
      
    } catch (Exception e) {
      // 这里是出了问题时怎么处理的
      System.out.println("CCC");
      return -1;

    } finally {
      // 最后的收尾动作,finally中不要写retrun,不然前面的结果不能返回
      System.out.println("DDD");
      return -2;
    }
  }
}

先执行try中的代码块,如果没有报错则在return前执行finally中的代码块

如果try中的代码块有报错,则执行catch中的代码块,在return前执行finally中的代码块

如果finally中有return,则不会执行try中代码块的return和catch中的代码块,所以一般finally中的代码块一般不写return

五、常用写法

public class App {

  public static void main(String[] args) {

    demo01();
  }

  private static void demo01() {
    try {
      // 被检查的代码块
      new FileInputStream(new File("test.log"));
    }catch (IllegalStateException ex){
      // 第一个要处理的异常
      ex.printStackTrace();
    }catch (IllegalFormatException ex){
      // 第二个要处理的异常
      ex.printStackTrace();
    }catch (IllegalArgumentException ex){
      // 第三个要处理的异常
      ex.printStackTrace();
    }catch (IOException ex){
      // 第四个要处理的异常
      ex.printStackTrace();
    }finally {
      // 最终怎么做
      System.out.println("异常处理完成");
    }
  }
}

六、自定义异常

如果要自定义异常类,则继承Exception类即可,因此这样的自定义异常都属于受检异常(checked exception)。如果要自定义运行时异常,则继承自类RuntimeException。按照惯例,自定义的异常应该总是包含如下的构造函数:

  • 一个无参构造函数;
  • 一个带有String参数的构造函数,并传递给父类的构造函数;
  • 一个带有String参数和Throwable参数,并都传递给父类构造函数;
  • 一个带有Throwable 参数的构造函数,并传递给父类的构造函数;

如下:

public class TestException extends RuntimeException {

  public TestException() {
  }

  public TestException(String message) {
    super(message);
  }

  public TestException(String message, Throwable cause) {
    super(message, cause);
  }

  public TestException(Throwable cause) {
    super(cause);
  }
}
TestException

调用如下:

public class App {

  public static void main(String[] args) {

    demo01();
  }

  private static void demo01() {
    throw new TestException("测试异常:TestException");
  }
}

运行结果:

 

标签:体系,Java,void,demo01,static,catch,异常,public
来源: https://www.cnblogs.com/L-Test/p/11477420.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有