合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
## 概述 是java代码编译或者运行过程中出现的问题. ## 异常的继承体系 1. Exception(普通问题):平时指的异常是这个.平时开发只研究异常,不研究错误. 2. Error(严重的问题):比如语法错误,如果程序出现了错误,只能改代码. 3. 共同的父类Throwable ## 异常分类 1. 编译时异常:指的是Exception以及Exception子类(RuntimeException除外). 2. 运行时异常:指的是RuntimeException以及RuntimeException的子类. ## 异常基本操作 1. 创建异常对象(JDK已自定义异常会自动创建对象,自定义异常需要手动创建) 2. 抛出异常(不处理异常,不处理也是一种处理),JVM报错. 3. 捕获异常(处理异常). ## 注意 异常处理,指处理的一种可能性,即有了异常处理的代码,不一定会产生异常.如果没有产生异常,则代码正常执行,如果产生了异常,则终端当前执行代码,执行异常处理代码. 1.运行时异常被抛出可以不处理,即不捕获也不声明抛出. 如果父类方法抛出了多个异常,子类重写父类方法时,只能抛出相同的异常或者该异常的子类异常. 2. 父类方法没有抛出异常,子类异常重写父类方法时也不可抛出异常.此时子类产生该异常,只能捕获处理,不能声明抛出(多线程会用到这个) 3. 当多异常处理时,捕获处理,前边的类不能是后面类的父类. 4. 在try/catch之后可以追加finally代码块,其中的代码一定会被执行,通常用于资源回收. ## 异常产生的过程 默认的方式叫中断处理方式. throw new 是虚拟机自动new的对象,它会根据异常的类型来new对象,thorw的目的是看看有没有程序来处理异常,如果没有程序处理异常,那么程序会中断执行. ![](https://box.kancloud.cn/1a1c2c77f000c8991aa36a04756042f8_1201x431.png) ## 模拟虚拟机产生异常 ~~~ public class ExceptionDome { public static void main(String[] args) { int[] nums = {1, 2}; System.out.println(getNum(nums)); System.out.println("hello"); //这里执行不了 } public static int getNum(int[] nums) { if (nums.length <= 2) throw new ArrayIndexOutOfBoundsException("索引越界"); //只要执行到了throw异常肯定抛出了 return nums[2]; } } ~~~ ![](https://box.kancloud.cn/a1cc3239f34e2537560ccb556fcbf9e5_1448x254.png) ## 异常处理的第一种方式(不处理,或者叫再次申明操作) 使用throws(形容词),形容可能抛出的异常名称.处理异常是处理的一种可能性. throws表示某一个方法可能抛出XX异常,要求调用者去处理它. 也可以叫做 ### 格式 ~~~ public static int getNum(int[] nums) throws ArrayIndexOutOfBoundsException , XXException { } ~~~ ## 异常处理的第二种方式(捕获处理) ### 格式 ~~~ try{ //可能出现异常的代码 }catch (Exception e){ //处理异常 }finally{ //必须要执行代码,比如释放资源的代码 } ~~~ ## 其他的处理方式一 (多个异常分别处理) 看起来很清晰,但是很少用,增加了代码量. ~~~ FileReader fr = null; try { fr = new FileReader("1.xxx"); } catch (IOException e) { System.out.println("打开文件失败"); } try { int ch = fr.read(); } catch (IOException e) { System.out.println("读取文件失败"); } try { fr.close(); } catch (IOException e) { System.out.println("关闭文件失败"); } ~~~ ## 其他的处理方式二 (多个异常一次捕获,多次处理) 这种方式也不常用. 要注意catch异常类型的顺序.下面两个异常类型就不能颠倒顺序,否则报错,多个异常如果有子父类关系,必须把子类异常写在前面. ~~~ FileReader fr = null; try { fr = new FileReader("1.xxx"); int ch = fr.read(); fr.close(); } catch (FileNotFoundException file) { System.out.println("关闭文件失败"); } catch (IOException io) { System.out.println("文件读取或者关闭失败"); } ~~~ ## 其他的处理方式三 (多个异常一次捕获,一次处理) 最常用,一个try,一个catch. ~~~ FileReader fr = null; try { fr = new FileReader("1.xxx"); int ch = fr.read(); } catch (IOException io) { System.out.println("文件读取或者关闭失败"); } finally { try { fr.close(); } catch (IOException e) { System.out.println("文件关闭失败"); } } ~~~ ## 运行时异常 如何区分一个异常到底是编译时一场还是运行时异常. 1. 编译时异常:在编译的时候会报错的(需要我们去处理) 2. 运行时异常:在编译的时候不会报错.只要定义一个方法,在方法中抛出一个异常对象,如果编译报错那么就是编译时异常,如果编译成功,那么就是运行时异常. ## 自定义异常 1. 类名必须要以Exception结尾. 2. 必须继承Exception或RuntimeException. 3. 至少有两个构造,一个是空参的,一个是客接收String类型的. ~~~ public class PersonException extends Exception { public PersonException() { super(); } public PersonException(String s) { super(s); } } ~~~ ## 实例 ~~~ public class NoSuchAgeException extends Exception { public NoSuchAgeException() { super(); } public NoSuchAgeException(String s) { super(s); } } ~~~ ~~~ public class Person { private String name; private int age; public Person(int age) throws NoSuchAgeException { if (age < 0 || age > 150) throw new NoSuchAgeException("年龄非法"); this.age = age; } } ~~~ ~~~ public class main { public static void main(String[] args) { try { Person p = new Person(200); } catch (NoSuchAgeException e) { e.printStackTrace(); } System.out.println("hello"); //自定义的异常程序会继续执行 } } ~~~