异常

一、异常分类

异常类层次结构图
在这里插入图片描述

在 Java 中,所有的异常都有一个共同的祖先 Throwable(可抛出)。Throwable 指定代码中可用异常传播机制通过 Java 应用程序传输的任何问题的共性。
Throwable: 有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类。
Error(错误): 是程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。例如,Java 虚拟机运行错误(Virtual MachineError),当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java 虚拟机(JVM)一般会选择线程终止。这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,如 Java 虚拟机运行错误(Virtual MachineError)、类定义错误(NoClassDefFoundError)等。这些错误是不可查的,因为它们在应用程序的控制和处理能力之 外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。在 Java 中,错误通过 Error 的子类描述。
Exception(异常): 是程序本身可以处理的异常。
Exception 类有一个重要的子类 RuntimeException。RuntimeException 类及其子类表示“JVM 常用操作”引发的错误。例如,若试图使用空值对象引用、除数为零或数组越界,则分 别 引 发 运 行 时 异 常 NullPointerException 、ArithmeticException 和 ArrayIndexOutOfBoundException。
注意:异常和错误的区别:异常能被程序本身可以处理,错误是无法处理。

二、抛出异常

  • 异常举例
public class Test2 {
    public static void CMDCalculate(){
        Scanner scan = new Scanner(System.in);
        int num1 = scan.nextInt();
        int num2 = scan.nextInt();
        int result = devide(num1,num2);
        System.out.println("result:"+result);
        scan.close();
    }
    public static int devide(int num1,int num2){
        return num1/num2;
    }

    public static void main(String[] args)  {
        CMDCalculate ();
    }

在这里插入图片描述

  • 编译期间就不通过的异常
    public static void fun1() throws IOException {//这里不抛出将会报错
        FileInputStream fileIn = new FileInputStream("C:\\1.text");
        int word;
        while ((word = fileIn.read())!= -1){//read 方法会抛出 IOException
            System.out.print((char)word);
        }
        //close 方法会抛出 IOException
        fileIn.close();
    }
  • 手动抛出异常
    public static void main(String[] args)  {
       //手动抛出异常,可以给异常带有参数
        String str = null;
        if (str == null){
            throw new NullPointerException("str == null");
        }
    }

在这里插入图片描述

  • 程序自己抛出异常,然后捕获
    public static void main  (String[] args) {
        try{
            int a = 10;
            int d = a/0;
            System.out.println(d);
        }catch (ArithmeticException e){
            System.out.println("ArithmeticException异常");
            e.printStackTrace();
        }
    }

在这里插入图片描述

    public static void main(String[] args) {
        try {
            int[] array = {1,2,3,4};
            System.out.println(array[4]);
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("数组越界异常");
            e.printStackTrace();
        }
    }

在这里插入图片描述

  • try ……catch……finally 捕获多个异常
    • 在一个try语句块中可以捕获多个异常类型,并对不同的异常做不同的处理
    public static void CMDCalculate(){
        //这里已经处理了异常,不需要再声明异常了
        //如果加了声明,当前函数就不处理了,调用该函数的一方进行处理。
        Scanner scan = new Scanner(System.in);
        try{
            int num1 = scan.nextInt();
            int num2 = scan.nextInt();
            int result = devide(num1,num2);
            System.out.println("result:"+result);
        }catch (ArithmeticException e){
            System.out.println("ArithmeticException异常");
            e.printStackTrace();
        }catch (InputMismatchException e){
            System.out.println("InputMismatchException异常");
            e.printStackTrace();
        }finally {
            scan.close();
            System.out.println("执行finally块语句");
        }
    }

在这里插入图片描述

三、自定义异常

class SimpleException extends Exception{
    //自定义异常类,继承Exception基类
}
public class Test2 {
    public static void fun() throws SimpleException{
        System.out.println("throws SimpleException");
        throw new SimpleException();//可以给参数
    }

    public static void main(String[] args) {
        Test2 test2 = new Test2();
        try{
            test2.fun();
        } catch (SimpleException e) {
            System.out.println("SimpleException caught it");
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

  • 可以写带有参数和不带有参数的
class SimpleException extends Exception {
    //自定义异常类,继承Exception基类
    public SimpleException() {

    }

    public SimpleException(String ss) {
        super(ss);
    }

四、执行顺序

  • finally 语句块在 try 语句块中的 return 语句之前执行
public class Test2{
    public static void main(String[] args) {
        try{
            System.out.println("try block");
            return;
        }finally {
            System.out.println("finally block");
        }
    }
}

在这里插入图片描述

  • finally 语句块在 catch 语句块中的 return 语句之前执行。
public class Test2{
    public static int test(){
        int i = 1;
        try{
            System.out.println("try block");
            i = 1/0;
            return 1;
        }catch (Exception e){
            System.out.println("exception block");
            return 2;
        }finally {
            System.out.println("finally block");
        }
    }
    public static void main(String[] args) {
        System.out.println("return value of test() : " + test());
    }
}

在这里插入图片描述

  • finally 中的 return 会覆盖 try 或者 catch 中的返回值
   public static int fun1(){
       try{
           int a = 5/0;
       }catch (Exception e){
           return 1;
       }finally {
           return 2;
       }
   }
    public static void main(String[] args) {
       int result = fun1();
        System.out.println(result);
    }
}

在这里插入图片描述

   public static int fun2(){
       try {
           return 1;
       }finally {
           return 2;
       }
   }
    public static void main(String[] args) {
       int result = fun2();
        System.out.println(result);
    }
}

在这里插入图片描述

try…catch…finally…中的return只要能执行,就都执行了,他们共同向一个内存地址写入返回值,后执行的将覆盖先执行的数据,而真正被调用者取的返回值就是最后一次写入的。

  • 终极顺序
public class Test2{
    
  public static String test(){
      try{
          System.out.println("try block");
          return test1();
      }finally {
          System.out.println("finally block");
      }
  }

  public static String test1(){
      System.out.println("return statement");
      return "after return";
  }

    public static void main(String[] args) {
        System.out.println(test());
    }
}

在这里插入图片描述

return test1();这条语句等同于 :
String tmp = test1(); 
return tmp;
public class Test2{
    public static int foo() throws Exception {
        try {
            int a = 5/0;
            return 1;
        }catch(ArithmeticException amExp) {
            throw new Exception("我是Exception异常 ");//ignore
        }finally {
            return 100;
        }
    }
    //try中的异常被抑制

    public static void main(String[] args) {
        int result;
        try{
            result = foo();
            System.out.println(result);           //输出100
        } catch (Exception e){
            System.out.println(e.getMessage());    //没有捕获到异常
        }
    }
}

在这里插入图片描述

注意
  1. 不要在 finally 中使用 return
  2. 不要在 finally 中抛出异常
  3. 减轻 finally 的任务,不要在 finally 中做一些其它的事情,finally 块仅仅用来释放资源是最合适的
  4. 尽量将所有的 return 写在函数的最后面,而不是 try … catch … finally 中
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值