初识异常
1、异常的体系
- 异常都是归属于类
Throwable
中- 子类分为Error 错误,这个是有JVM产生,程序员无法修改
- Exception 这个分编译时和运行时产生
2、异常的分类
-
编译时异常
Checked Exception
,正常这类异常在idea开发的时候就会提示,需要人为指定处理方案,如果程序运行到这里时发生了异常,该怎么处理,不发生异常该怎么处理 -
运行时异常
RuntimeException
,这类异常在编译时不会报错,但是运行后肯定会发生异常,发生异常后,程序会停止在异常发生的地方停止运行,后续代码也不会执行。-
常见的几个运行时异常
1、空指针异常
2、数组下标越界异常
3、类型转换异常
4、栈溢出异常
5、算术异常
-
3、不同异常的处理方案
-
Java有2种异常解决方案
-
抛出
通过关键字
throws
将可能发生的异常从本方法抛出到上一级的方法,不会处理 -
捕获
通过
try/catch
来实现捕获并处理异常/** 异常判断顺序时从第一个catch开始从上往下开始判断异常,符合就执行,如果catch内容都未匹配上就会执行finally的内容 如果try中有异常发生,程序就会在异常处停止,接下来的代码不会再次执行,即使异常捕获处理后也是 */ try{ 可能会出现异常的代码块 }catch(可能会出现的异常){ 出现该异常后执行的代码块 }catch(Exception e){//这句就是如果上述的可能出现的异常没有,但是确实有异常发生,全部被e接收并执行该代码块 出现该异常后执行的代码块 }……finally { 这句时最终必须要执行的代码块//如果出现了finally 代表这里的代码块一定会执行到 }
异常处理还是比较重要
package com.yjxxt.exception; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; /* 异常处理方案 : ***** 异常抛出 : throws 从方法的内部抛出到当前上面 异常捕获 : try catch try{ 有可能出现异常的代码段; }catch(异常类型 e){ 出现异常后执行的代码; }catch(异常类型 e){ 出现异常后执行的代码; }..... finally{ 如果是try中会出现异常,无论出现了异常执行了哪一个catch,最后都会执行finally中的代码 } 注意: 一个try后面可以接1~n个catch catch会从上到下判断执行 try中的代码如果出现异常,不会执行catch的判断 如果try中一旦出现了异常,直接执行对应catch的判断,try中后面的代码不会执行 如果是try中会出现异常,无论出现了异常执行了哪一个catch,最后都会执行finally中的代码 finally中一般定义为资源的关闭等 思考: 如果在try中遇到方法的return,会直接结束呢还是 要执行finally中的代码然后再结束呢??? */ public class Class002_Exception { public static void main(String[] args){ try { System.out.println("try开始了"); test(); //System.out.println(5/0); System.out.println("try结束了"); } catch (FileNotFoundException e) { //e.printStackTrace(); /*打印异常的栈信息*/ System.out.println("文件找不到啦!!!!"); } catch(Exception e){ System.out.println("接盘侠"); } finally { System.out.println("最终肯定会执行的代码"); } System.out.println("main方法结束"); } public static void test() throws FileNotFoundException { InputStream is = new FileInputStream("D://test.txt"); } }
-
4、自定义异常
-
自定义异常类是指在Java中满足Java的语法格式,不会报错和出现异常,但是实际情况中不可能出现,比如限制用户输入的年龄,如果属性定义的是
int
类型,而int
又包括负数,但是实际情况中不可能出现负数的年龄,所以在识别用户输入负数时就要提示异常并停止程序运行。那么就需要自定义这个异常类的规则,满足情况就产生一异常中止程序。 -
一般来说自定义异常都是直接或者间接的继承自
Exception
-
运行时异常同样时直接或者间接的继承
RuntimeException
-
制造异常通过
throw
(而throws
是抛出异常)package com.yjxxt.exception; /* 自定义异常: 1) 自定义的异常类要求直接或者间接的继承自Exception 2) 运行时期异常要求直接或者间接继承自RuntimeException 3) throw 制造异常 -> throw与throws之间的区别 4)编译时异常与运行时期异常的定义选择: 如果要求极度严格(文本是否存在对于从文件中读取内容来说非常重要,极有可能不存在,不满足条件,所以文件未找到异常就为编译时异常),这种异常类可以定义为编译时期异常,在编译期间,必须提供备选方案(catch) 如果要求没那么严格,偶尔可能 出现的不满足条件的情况遇到异常,这种异常类可定义为运行时期异常,比如(空指针),增强程序的健壮性就能解决 */ public class Class003_DefinedException { public static void main(String[] args) { User user = new User(); user.setName("老薛"); int age = -20; /* if(age>=18 && age<=50){ user.setAge(age); }else{ user.setAge(18); }*/ try { user.setAge(age); } catch (AgeException e) { try { user.setAge(17);//因为调用的这个方法可能会产生异常,所以必须要先给解决方案,是向上抛出还是捕获解决 } catch (AgeException ageException) { ageException.printStackTrace();//打印异常的栈信息 } } System.out.println(user); } } //自定义异常类 //class AgeException extends RuntimeException{ //运行时异常 在编译时不会提示,程序可以运行但是会报错 一般哦通过增加if判断来提高代码的健壮性 class AgeException extends Exception{ //编译时异常 如果不处理程序不能运行 public AgeException() { } //调用了父类的有参构造器 public AgeException(String message) { super(message); } } //声明一个类 class User{ private String name; private int age; public User() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) throws AgeException { //年龄不合法抛出异常 if(age<18 || age>50){ throw new AgeException(age+"不合法!!!"); } this.age = age; } //重写了toString方法 @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } }