java核心(16):异常处理

一、throw 和 throws 的用法
    1、throw:异常的抛出
  • 定义 : 一个方法不处理这个异常,而是调用层次向上传递,谁调用这个方法,这个异常就由谁来处理。
  • 位置:在方法体内使用throw,进行异常抛出
  • 语法:将产生的异常抛出(强调的是动作),抛出的既可以是异常的引用,也可以是异常对象。
public void todo() throws Exception {
throw new Exception("除数不能为0");
}
    注意 : 调用可能会抛出异常的方法,必须添加 try-catch 代码块尝试去捕获异常 ,或者 添加throws 声明 来将异常 抛出给更上一层的调用者进行处理。这里需要注意一个细节:新的异常包含原始异常的所有信息,根据这个我们可以去追溯最初异常发生的位置,
public class TestException {
    /**
     * 通过throw抛出异常: throw new Exception("除数不能为0")
     * 由于抛出的是Exception对象(包含受检异常和非受检异常),所以需要在方法声明时指定throws
     */
    public static void devide(int numOne ,int numTwo) throws Exception{
        if(numTwo == 0) {
            throw new Exception("除数不能为0");
        }
        System.out.println("-----1111111--------");
        System.out.println("计算结果:"+(numOne / numTwo));
        System.out.println("-----2222222--------");
    }
 
    /**
     * 调用异常方法时,需要通过try/catch,进行异常处理
     *  如果不处理,可将异常通过throws继续向上抛出
     */
    public static void todo(int numOne,int numTwo){
        try {
            devide(numOne,numTwo);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("-----3333333--------");
    }
 
    /**
     * 不处理异常,将异常通过throws继续向上抛出
     */
    public static void notHandel(int numOne,int numTwo) throws Exception {
        devide(numOne,numTwo);
    }
 
    /**
     * 主方法*/
    public static void main(String[] args)  {
       todo(28,7);
    }
}
//程序执行结果:
-----1111111--------
计算结果:4
-----2222222--------
-----3333333--------

 

2、throw 和 throws 的区别
  throw throws
意义 强调动作,指方法主动抛出异常 表示一种倾向、可能会抛出异常,但不一定实际发生
使用位置 在方法体内使用 在方法名或参数列表后、方法体前使用
语法定义 后跟的是异常对象,或者异常对象的引用 后跟的是异常类,可以一个,可以多个,多个用逗号隔开
对方法的影响 throw用户抛出异常,当在当前方法中抛出异常后,当前方法执行结束(throw 后,如果有finally语句的话,会执行到finally语句后再结束。)。可以理解成return一样。 throws : 如果一个方法可能会出现异常,但没有能力处理这种异常,可以在方法声明处用throws子句来声明抛出异常。用它修饰的方法向调用者表明该方法可能会抛出异常
 
 
二、RuntimeException运行时异常
1、运行时异常定义
  程序在运行过程中出现的异常,称为运行时异常,RumtimeException 是 Exception 的一个子类 。
public class RuntimeException extends Exception {
    …….
}

 

2、运行时异常的使用
  自定义异常时,如果该异常的发生,无法继续进行后续的运行,就让自定义异常类继承运行时异常RuntimeException。
/**
 * 自定义异常
 */
class MyException extends RuntimeException{
    public MyException() {
    }

    public MyException(String message) {
        super(message);
    }

    public MyException(String message, Throwable cause) {
        super(message, cause);
    }

    public MyException(Throwable cause) {
        super(cause);
    }

    public MyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

 

 3、运行时异常的特点
  一般来说,我们在方法体内出现异常,我们用throw 关键字 将 异常对象或 异常对象的引用抛出,如果当前方法无法处理异常,那么必须在方法的参数列表后方法体前 必须 用 throws 声明异常所属类,交给调用者去处理。
  但是RuntimeException是非常特殊的子类,你可以不用throw和throws,哪怕你throw了,也没必要thtows,即使你throws了,调用者也没必要try-catch
  • 如果在函数内容中抛出该类异常或其子类异常,函数上可以不用声明,编译一样通过
  • 如果在函数上声明该异常,调用者可以不同处理(try-catch),编译一样通过
  为什么不用声明 ?
  之所以不用在函数上声明,是因为不需要让调用者处理,当该异常发生,希望程序停止,因为在运行时,出现了无法继续运算的情况,希望程序停止后由程序员对代码进行修正。
 
public class TestException {
    /**
     * throw抛出的是运行时异常,所以不需要调用者去处理(因此不需要加throws)
     */
    public static void devide(int numOne ,int numTwo) {
        if(numTwo == 0) {
            throw new RuntimeException("除数不能为0");
        }
        System.out.println("-----1111111--------");
        System.out.println("计算结果:"+(numOne / numTwo));
        System.out.println("-----2222222--------");
 
    }
 
 
    /**
     * 调用者不需要处理运行时异常
     */
    public static void todo(int numOne,int numTwo){
        devide(numOne,numTwo);
    }
 
 
    /**
     * 主方法
     */
    public static void main(String[] args)  {
       todo(28,7);
    }
}
//程序执行结果:
-----1111111--------
计算结果:4
-----2222222--------

 

三、ckecked异常(受检异常) 和 运行时异常 :二者的区别
 
  异常分两种:检查异常和非检查异常(运行时异常)
  • 检查异常 : 编译时能够被检测的异常 (throw后,方法有能力处理就try-catch处理,没能力处理就必须throws)。编译不通过,检查语法(其实就是throw和throws的配套使用)。
  • 运行时异常 : 编译时不被检查的异常(运行时异常。RuntimeException及其子类)。编译通过。
  
1、机制上的区别
  主要表现在以下两个方面 : 
  • (1)如何定义方法 
  • (2)如何处理抛出的异常
   运行时异常,不需要用throws 声明抛出 异常对象所属类,也可以不用throw 抛出异常对象或异常引用。对于调用该方法,也不需要放于 try-catch 代码块中。(为什么 ? 如果你捕获它,就会冒这么一个风险:程序代码错误被掩盖在运行中无法察觉)
  而检查异常 : 一旦 用throw 抛出异常,必须被处理。如果当前方法可处理异常,那么直接在该方法内用try-catch 去处理。如果当前方法不具备处理该异常的能力,那么就必须在参数列表后方法体前用 throws 声明异常所属的类,交给调用者(方法) 去处理 。
 
2、逻辑上的区别
  从逻辑的角度来看, checked 异常 和 RuntimeException 有着不同的使用目的检查性异常用来指示一种调用方能够直接处理的异常情况(例如: 用户输入错误,程序可以直接捕获并处理,提示用户输入错误), 而RuntimeException是用来指调用方本身无法处理或回复的程序错误(例如,你封装个类库给别人用,当别人调用你库中某个方法是,需要传入某些参数,如果用户传入的参数不合法,你自己没办法处理,那么此刻你抛出的就应该是运行时异常)。
 
被博客部分内容转载自CSDN:
原作者:YFL_iOS 
原文地址:https://blog.csdn.net/qq_18505715/article/details/76696439

 

posted @ 2019-04-19 18:10  荆小六  阅读(253)  评论(0编辑  收藏  举报