Java异常

异常是在程序中导致程序中断运行的一种指令流  

所有的异常都有⼀个共同的父类 java.lang 包中的 Throwable 类。Throwable: 有两个重要的子类:Exception(异常) 和 Error(错误) (都有大量子类)。

  • Exception :程序本身可以处理的异常,可以通过 catch 来进行捕获,通常遇到这种错误,应对其进行处理,使应用程序可以继续正常运行。 Exception 又可以分为运行时异常 (RuntimeException, 又叫非受检查异常)和编译时异常(又叫受检查异常)
  • Error : Error 表示系统级的错误, 是 java 运行环境内部错误或者硬件问题,是程序无法处理的错误 ,无法通过 catch 来进行捕获 比如Virtual MachineError ,系统崩溃,内存不足,堆栈溢出等.遇到Error只能停止运行, 它是 Java 虚拟机抛出的。 

NoClassDefFoundError 和 ClassNotFoundException 区别 

NoClassDefFoundError 是一个 Error ,是由 JVM 引起的,不应该尝试捕获这个异常。引起该异常的原因是 JVM 或 ClassLoader 尝试加载某类时在内存中找不到该类的定义,该动作发生在运行期 间,即编译时该类存在,但是在运行时却找不到了,可能是编译后被删除了等原因导致。

ClassNotFoundException 是一个受检查异常,需要用try-catch对其进行捕获和处理或用throws向上抛出给调用者当使用 Class.forName, ClassLoader.loadClass 或 ClassLoader.findSystemClass 动态加载类到内存的时候,通过传入的类路径参数没有找到该类,就会 抛出该异常;还有 可能某个类已经由一个类加载器加载至内存中,另一个加载器又尝试去加载它。

非受检查异常(运行时异常)和受检查异常(编译时异常)的区别 

非受检查异常:包括 RuntimeException 类及其子类,表示 JVM 在运行期间可能出现的异常。 Java 编译器不会检查运行时异常。比如

  •  NullPointException(空指针)
  •  NumberFormatException(字符串转换为数字)
  •  IndexOutOfBoundsException(数组角标越界)
  •  ClassCastException(类转换异常)
  •  ArrayStoreException(数据存储异常,操作数组时类型不一致)
  •  ArithmeticException:(算术条件异常)
  • ......

受检查异常:是Exception 中除 RuntimeException 及其子类之外的异常。 Java 编译器会检查受检查异常。常见的受检查异常有: IO 相关的异常、 ClassNotFoundException 、 SQLException 等。

非受检查异常和受检查异常之间的区别:受检查异常强制要求调用者必须处理此异常( 捕获或者向上抛出否则无法通过编译,是⼀种强制规范),非受检查异常可以不处理(在运行期如果发生异常该方法就会创建一个异常对象然后向上抛出异常(最终交给JVM)中断程序的运行并打印异常信息)。

异常是否抛出?如果因为传递的参数导致的异常,应该通过throws将异常抛出

Throwable类常用方法

  • public string getMessage():返回异常发生时的简要描述
  • public string toString():返回异常发生时的详细信息
  • public void printStackTrace():在控制台上打印 Throwable 对象封装的异常信息 

异常体系结构

异常指的是Exception , Exception类, 在Java中存在一个父类Throwable(可能的抛出) Throwable存在两个子类:

  1. Error:表示的是错误,是JVM发出的错误操作,只能尽量避免,无法用代码处理。
  2. Exception:表示所有程序中的错误,所以一般在程序中将进行try…catch的处理。

处理异常

程序中产生了异常,异常之后的语句将不再执行,所以程序没有正确执行完毕就退出。 为了保证程序出现异常之后仍然可以正确的执行完毕,所以采用异常的处理机制。

正确处理异常 异常的处理方式有两种。 1、 自己处理。 2、 向上抛(交给调用者处理)。 异常,千万不能捕获了之后什么也不做。或者只是使用e.printStacktrace。 具体的处理方式的选择其实原则比较简明:明确知道如何处理的,就要处理掉。 不知道如何处理的,就交给调用者处理。

 public static void test()  {
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入数字");
        String s = scanner.nextLine();
        try {
            int a = Integer.parseInt(s);
        } catch (NumberFormatException e) {
//            e.printStackTrace();不仅仅是打印
            test3();//既然不符合要求,就处理(此处重新输入)
        }
    }

 try 块: 用于捕获异常。其后可接零个或多个 catch 块,如果没有 catch 块,则必须跟⼀个 finally块。

catch 块: 用于处理 try 捕获到的异常。

finally 块: 无论是否捕获或处理异常,此语句将作为异常的统一出口,不管是否产生了异常,最终都要执行此段代码。当在 try块或 catch 块中遇到 return 语句时,finally 语句块将在方法返回之前被执行(具体见Java异常finally与方法返回值)。一般资源的关闭会放在finally代码段中执行

在以下 4 种特殊情况下,finally 块不会被执行:

  1.  在 finally 语句块第一行发生了异常,除了第一行,finally 块还是会得到执行
  2.  在前面的代码中用了 System.exit(int)已退出程序。 exit 是带参函数 ;若该语句在异常语句   之后,finally 会执行
  3.  程序所在的线程死亡
  4.  关闭 CPU

处理异常格式:

try{
  // 有可能发生异常的代码段
}catch(异常类型1 对象名1){
  // 异常的处理操作
}catch(异常类型2 对象名2){
// 异常的处理操作
} ...
finally{
// 异常的统一出口
}

try+catch的处理流程

  •  一旦产生异常,则系统会自动产生一个异常类的实例化对象
  • 此时如果异常发生在try语句,则会自动找到匹配的catch语句执行,如果没有在try语句中,则会将异常抛出.
  • 所有的catch根据方法的参数匹配异常类的实例化对象,如果匹配成功,则表示由此catch进行处理。

多异常捕获要注意:

  •  捕获更粗的异常不能放在捕获更细的异常之前。
  •  如果为了方便,则可以将所有的异常都使用Exception进行捕获。

特殊的多异常捕获写法: catch(异常类型1 |异常类型2 对象名){ //表示此块用于处理异常类型1 和 异常类型2 的异常信息 }

throws关键字

主要在方法的声明上使用,表示方法中不处理异常,而交给调用者处理。主要是声明这个方法会抛出类型的异常,让其调用者知道需要捕获的异常的类型。throws表现异常的一种可能性,并不一定会发生这种异常。

格式:

返回值 方法名称()throws Exception{
}

throw关键字

throw关键字表示在程序中人为抛出一个异常,因为从异常处理机制来看,所有的异常一旦产生之后,实际上抛出 的就是一个异常类的实例化对象,throw被执行后面的语句不起作用,直接转入异常处理的阶段

实例: throw new Exception("我的定制异常") ;

 class MyException extends RuntimeException{
    public MyException(String message) {
        super(message);
    }
}
class HisException extends Exception{
    public HisException(String message) {
        super(message);
    }
}
    public static void main(String[] args) {
        test(-1);
        try {
            test2(-3);
        } catch (HisException e) {
            e.printStackTrace();
        }
    }
    public static void test(int a){
        if (a<0){
            throw new MyException("不能小于0");
        }
    }
    public static void test2(int a) throws HisException {
        if (a<0){
            throw new HisException("不能小于0");
        }
    }

 注意:自行抛出的运行时异常不用手动抛出,运行时会自动向上抛至JVM,但是编译时异常需要向上抛,让调用者处理

自定义异常类 (了解)

自定义异常通过继承 Exception 的子类的方式实现。 编写自定义异常类实际上是继承一个 API 标准异常类,用新定义的异常处理信息覆盖原有信息的过程。 这种用法在 Web 开发中比较常见,一般可以用来自定义业务异常。如余额不足、 重复提交等。这种自定义异常有业务含义,更容易让上层理解和处理。

class MyException extends Exception{
    public MyException(String msg){
        super(msg) ;  //在这里给维护人员发短信或邮件, 告知程序出现了BUG。
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值