异常

三种异常类型

  1. 检查性异常:最具代表的检查异常时用户错误或问题引起的异常,这是程序员无法预见的,例如要打开一个不存在的文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。

  2. 运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。

  3. 错误ERROR:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。

 

Throwable(异常的超类)

  1. ERROR(错误)

    • VirtulMachineError(虚拟机异常)

      • StackOverFlowError

      • OutOfMemoryError

    • AWTError(GUI编程图形界面化异常)

  2. Exception(异常)

    • IOException(IO异常)

      • EOFException

      • FileNotFoundException

    • RuntimeException(运行时异常)

      • ArrithmeticException(算数异常)

      • MissingResourceException(丢失资源)

      • ClassNotFoundException(找不到类)

      • NullPointerException(空指针异常)

      • IllegalArgumentException

      • ArrayIndexOutOfBoundsException(数组下标越界异常)

      • UnkownTypeException(未知的类型异常)

Error与Exception区别

Error通常时灾难性的致命错误,时程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程;Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。

异常处理机制

  • 抛出异常

  • 捕获异常

  • 异常处理五个关键字:

    • try、catch、finally、throw、throws 

捕获异常 try...catch

捕获异常:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式处理。

捕获异常语法如下:

try:该代码块中编写可能产生异常的代码。

catch:用来进行某种异常的捕获,实现对捕获到的异常进行处理。

注意:try和catch都不能单独使用,必须连用。

Finally 块

有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到,而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。

什么时候的代码必须最终执行?

当我们在try语句块中打开了一些物理资源(如 IO流、网络、数据库链接等),都需在使用完之后,最终关闭打开的资源。

finally 的语法: try.....catch...finally:自身需要处理异常,最终还得关闭资源。

注意:finally 不能单独使用。

  

 1  package com.exception;
 2  public class Test {
 3      public static void main(String[] args) {
 4          int a=1;
 5          int b=0;
 6          //快捷键 ctrl+alt+t
 7          System.out.println(a/b);
 8          //要捕获多个异常:从小到大!
 9          try {//try监控区域
10              new Test().a(); 
11          }catch (ArithmeticException e){//catch(想要捕获的异常类型!) 捕获异常
12              System.out.println("程序出现异常,变量b不能为0" );
13          }catch (Error e){
14              System.out.println("Error");
15          }catch (Exception e){
16              System.out.println("Exception ");
17          } finally {//处理善后工作
18              System.out.println("finally");
19          }
20          //finally 可以不要finally 假设IO,资源,关闭!
21      }
22      public void a(){
23          b();
24      }
25      public void b(){
26          a();
27      }
28  } 
抛出异常 throw

在Java中,提供一个throw关键字,它用来抛出一个指定的异常对象。

  1. 创建一个异常对象。封装一些提示信息(信息可以自己编写)

  2. 需要将这个异常对象告知调用者。通过关键字throw将这个异常对象传递到调用者处。throw用在方法内,用来抛出一个异常对象,将使用格式: throw new 异常类名(参数---你想告知用户的异常信息);

注意:如果产生了问题,我们通过throw将异常进行抛出,也就是将问题返回给该方法的调用者。那么调用者该怎么处理那?一种是进行捕获处理,另一种就是继续将问题生命出去,使用throws声明处理。

声明异常 throws

将问题标识出来,报告给调用者。如果方法内通过throw抛出了 编译时异常,而没有捕获处理,那么必须通过throws 进行声明,让调用者去处理。关键字 throws 运用于方法声明上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常)。

声明异常语法: 修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2...{}

throws 用于进行异常的声明,若该方法可能有多种异常情况产生,那么在 throws 后面可以写多个异常类,用逗号隔开。最大的异常习惯放后面。

异常处理两种方式

如果异常出现的话,会立刻终止程序,所以我们得处理异常:

  1. 声明异常:throws该方法不处理,而是声明可能出现的异常,将问题暴露给调用者,让调用者自己处理!

  2. 捕获异常:try catch 在方法中使用try-catch的语句块直接处理可能出现的异常!

 1  package com.exception;
 2  public class Test2 {
 3      public static void main(String[] args) {
 4          try {
 5              new Test2().test(1,0);
 6          }catch(ArithmeticException e){
 7              e.printStackTrace();
 8          }
 9      }
10      //假设这方法中,处理不了这个异常。方法上抛出异常
11      public void test(int a,int b){
12          if(b==0){//throw throws
13              throw new ArithmeticException();//主动的抛出异常,一般在方法中使用
14          }
15      }
16  }

异常注意事项

多个一擦汗给你使用捕获又该如何处理?

  1. 多个异常分别处理。

  2. 多个异常一次捕获,多次处理。

  3. 多个异常一次捕获一次处理。

一般我们使用一次捕获多次处理的方法,格式如下:

1 try{
2     //可能出现异常的代码
3 }catch(异常类型A e){//当 try 中出现A类型异常,就用该catch来捕获
4     //处理异常的代码
5     //记录日记/打印异常信息/继续抛出异常
6 }catch(异常类型B e){//当 try 中出现B类型异常,就用该catch来捕获
7     //处理异常的代码
8     //记录日记/打印异常信息/继续抛出异常
9 }

注意:这种处理方式,要求多个catch中的异常不相同,并且若catch中的多个异常之间有子夫类异常的关系,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理。

  • 运行时异常被抛出可以不处理,即不捕获也不声明抛出。

  • 如果finally有return语句,永远返回finally中的结果,避免该情况。

  • 如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。

  • 父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出。(throws)

自定义异常

在开发中根据自己业务的异常情况来定义异常类:

例如 自定义一个业务逻辑异常:PasswordErrorException。密码错误类。

异常类如何自定义:

  1. 自定义一个检查异常:自定义类 并继承于 java.lang.Exception

  2. 自定义一个运行时期的异常类:自定义类 并继承于 java.lang.RuntimeException

 1 public static void main(String[] args) {
 2         UserService ser =new UserService();
 3         try {
 4             //异常可以处理,也可以不处理:运行时异常
 5             boolean res1=ser.validateName("test1");
 6             System.out.println(res1);
 7         } catch (UserNameIsNotExistException e) {
 8             e.printStackTrace();
 9         }
10         try {
11             //必须处理异常:有可能是检查异常
12             boolean res=ser.login("teset1","teset");
13             System.out.println(res);
14         } catch (UserPwdErrorException e) {
15             e.printStackTrace();
16         }
17     }
 1 public class UserService {
 2     public boolean validateName(String name) {
 3         if(!name.equals("test")) {
 4             throw new UserNameIsNotExistException();
 5         }else {
 6             return true;
 7         }
 8     }
 9     public boolean login(String name,String pwd) throws UserPwdErrorException{
10         if(name.equals(pwd)) {
11             return true;
12         }else {
13             throw new UserPwdErrorException();
14         }
15     }
16 }
1 public class UserNameIsNotExistException extends RuntimeException{
2     public UserNameIsNotExistException() {
3         super("用户名不存在!");
4     }
5 }
1 public class UserPwdErrorException extends Exception{
2     public UserPwdErrorException() {
3         super("用户名或密码错误!");
4     }
5 }
posted @ 2020-06-08 15:29  不被替代的坚持  阅读(249)  评论(0编辑  收藏  举报