zoukankan      html  css  js  c++  java
  • Java

    异常处理

    异常分类与体系结构:

    image-20191121094447105

    Error 相关类型的异常是程序无法处理(大多都是修改代码无法解决的)的异常,这类异常通常需要我们调整JVM的运行环境

    Exception 相关类型的异常是程序可以处理的异常,其包含两大子类型

    • 编译异常(CheckedException)

      通常是语法错误,或是方法明确指明可能抛出异常则必须捕获处理

    • 运行时异常(RuntimeException)

      指的是检查阶段没有发现任何问题,满足所有语法规范,只有在运行时才能发现的异常

    异常处理

    关键字 try catch finally throws throw

    基本语法:

    image-20191121100239487

    注意:

    • try 无法单独使用,必须与catch 或finally 组合使用

    • finally 表示最终,即无论异常是否真的发生了,最终都会执行finally

    • 当异常类型为Exception时 表示通用异常处理(万能异常处理),可以捕获所有异常但是无法针对性的处理

    • 一个try可以有多个catch

    • 通常将Exception添加到最后一个catch中作为完全保证,让程序可以继续运行

    • 一个try中的所有catch下每个异常类型只能出现一次

    • catch中异常类型必须从小到大(先子类在父类)

    • 无论有多个catch最终只有一个会被执行(类似 if else.....)

    • 如要打断finally的执行可以直接退出虚拟机,System.exit();

    finally 对return的影响

    在方法中,如果有finally,即使在 try 或catch中遇到了return 语句,方法也不会立即结束,而是必须执行完finally后才会执行结束,

    案例:

    class Test{
      public static void main(String[] args){
    		System.out.println(func(0));
        //此处得到的结果为10000;
        //如果没有finally 则是10;
      }
      public static int func(int arg){
        try{
          int a = 1/arg;
          return a;
        }catch(Exception e){
          return 10;
        }finally{
          return 10000;
        }
      }
    }
    
    强调:方法中无论是否出现异常,返回值都以finally中的返回值为准,这是不符合实际的,所以通常不这么写

    抛出异常

    throws

    用于方法定义,在定义方法时可以使用throws来声明,方法可能会抛出某种类型的异常

    image-20191121103939422

    什么时候使用throws

    当方法中可能会有异常,但是方法本身无法处理,或是不想处理....就可以使用throws来抛出

    需要强调的是:如果一个异常抛出后没最终没有得到处理,将导致程序运行中断,所以通常我们不能放任不管

    使用

    image-20191121104306085

    注意:

    • 简单的说,只要声明了,则表明方法内部不会处理该异常,谁调用就由谁处理;

    • 相应的调用者则需要捕获异常并处理,若调用方也无法处理,则可以继续向上抛出

    • 一个方法也可以声明抛出多种不同类型异常,响应的调用方应增加对应的catch

    案例:

    package com.yh.test;
    
    public class Test {
        public static void main(String[] args){
           //一直抛向程序入口都没有得到处理则程序被终止
            func3();
        }
        static public void func2() throws ArithmeticException{
            int a = 1/0;
        }
    
        static public void func3() throws ArithmeticException{
            try{
                func2();//func2抛出异常
            }catch (Exception e){
               //无法处理则继续向上抛出
                throw e;
            }
        }
    }
    

    抛出多种类型异常:

    import java.util.InputMismatchException;
    import java.util.Scanner;
    
    public class Test {
        public static void main(String[] args){
            try {
                func3();
            } catch (ArrayIndexOutOfBoundsException e) {
                e.printStackTrace();
            } catch (InputMismatchException e) {
                e.printStackTrace();
            }
        }
        static public int func3() throws ArrayIndexOutOfBoundsException,InputMismatchException{//        try{
                int a = new Scanner(System.in).nextInt();
                return 10/a;
        }
    }
    

    throw

    主动抛出异常

    image-20191121110702483

    使用场景:

    当方法的提供者需要调用者提供一些数据,但是这些数据不合法,导致功能无法正常处理时,就应该主动抛出异常

    调用方可以在捕获到异常后进行处理

    抛出还是处理?

    方法内部导致的异常自己处理,调用者导致的异常则抛出(或者能处理则处理)

    疑惑:为什么throws Exception时编译器要求必须提供解决方案?

    因为Exception 既包含了运行时异常 又包含了 编译时异常,所以要求必须处理,由此可知,当throws声明的异常为编译时异常时则要求必须提供处理代码;

    案例:

    package com.yh.test;
    
    public class Test {
        public static void main(String[] args){
            try {
                func(1);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        static void func(int a) throws  Exception{
            if (a < 1){
                throw new Exception("参数不能小于1");
            }
        }
    }
    

    自定义异常

    当内置异常无法满足特点业务场景时,可以自定义异常类,只需要继承Exception即可

    案例:

    class MyException extends Exception{
        public MyException() {
            super("固定的异常提示!");
        }
    }
    

    当异常提示信息固定的时候可以像上面一样定义构造器

    异常链

    当一个方法抛出的异常被调用方法捕获,但是调用方法又抛出了新的异常时,则形成了异常链,

    如果我们在调用方法中直接抛出新的异常不做任何额外的操作时,原始异常信息则被丢失;

    我们有两个方法可以保留原始异常信息

    1.实例化时使用原始异常作为参数

    2.实例化后调用initCause传入原始异常对象

    案例:

    package com.yh.test;
    
    public class ExceptionLinkeTest {
        public static void main(String[] args) {
            try {
                func2();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        static public void fun1() throws ArithmeticException{
            int a = 1 / 0;
        }
    
        static public void func2() throws Exception{
            try{
                fun1();
            }catch (ArithmeticException e){
              	//不保留原始异常信息
                //throw  new Exception("新的异常信息!");
              
                //保留异常信息方法1
              	throw  new Exception("新的异常信息!",e);
              
                //保留异常信息方法2
    	          Exception newex = new Exception("新的异常信息!");
              	newex.initCause(e);
              	throw newex;          
            }
        }
    }
    

    当我们不做处理时,得到的异常信息如下:

    image-20191121115914351

    使用 方法1或方法2 来保留异常信息结果如下:

    image-20191121120017971

  • 相关阅读:
    UVA10763交换学生
    UVA10763交换学生
    UVA10391复合词
    UVA10391复合词
    UVA10125和集
    UVA10125和集
    POJ3762 时间段用k次
    POJ3762 时间段用k次
    Win64 驱动内核编程-11.回调监控进线程句柄操作
    Win64 驱动内核编程-11.回调监控进线程句柄操作
  • 原文地址:https://www.cnblogs.com/yangyuanhu/p/11909466.html
Copyright © 2011-2022 走看看