新的异常包含原始异常的所有信息,通过调用新异常的initCause()方法 ,去引用了原始异常,从而实现了异常链的功能。
throws是把异常抛出给上一级去处理
try catch就是直接捕获异常自己处理掉了,所以不用再抛出
第三种
super();
这种方法意义为,调用父类的初始化方法,其实就是调用父类中的public xxx()方法
追问
第三种在写代码的时候可以省略吗.?
追答
看情况,比如说,你自己从新封装了jdk里面的HashMap类 public class MyMap extends HashMap 这时候,如果你想在实际应用中使用自己的类代替系统中原有的HashMap,就需要写如下代码 public MyMap(){ super(); } 这样,你自己写的类 MyMap map = new MyMap();才能使用 这样做的好处是,你可以不知道原来父类的初始化构造函数是怎么写的。 但是却可以轻易封装它。
关键点:initCause建立异常链或初始化RuntimeException传参
try-catch中加入运行时异常语句可以定位运行时的异常位置
JAVA中的异常链
??????
。。。。,
。。。。。
不改msg,包装异常类型 向上抛
包装捕捉到的异常,继续向上抛出
package work1;
import java.util.Scanner;
public class BookManagerEasy {
private static Scanner sc = new Scanner(System.in);
//从控制台输入命令,用于输入命令和图书序号
private static int inputCommand(){
int command;
try{
command = sc.nextInt();
return command;
}catch(Exception e){
sc = new Scanner(System.in);//重新输入
return -1;
}
}
private static String getBookByName(String[] books)
throws Exception{
System.out.println("输入图书名称");
String name = sc.next();
for(int i = 0; i < books.length; i++){
if (name.equals(books[i])) {
return books[i];
}
}
//若无匹配,抛出”图书不存在异常“
throw new Exception("图书不存在!");
}
private static String getBookByNumber(String[] books)
throws Exception{
// TODO Auto-generated method stub
while(true){
System.out.println("请输入图书序号:");
try {
int index = inputCommand();
if (index == -1) {
System.out.println("命令输入错误!请根据提示输入数字命令!");
continue;
}
//若不出现”数组下标越界异常“,则返回相应位置的图书
String book = books[index];
return book;
} catch (ArrayIndexOutOfBoundsException e) {
// TODO: handle exception
e.printStackTrace();
//输入的序号不存在(引发”数组下标越界异常“),则抛出”图书不存在异常“
Exception bookNotExists = new Exception("图书不存在!");
bookNotExists.initCause(e);
throw bookNotExists;
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] books = { "C语言",
"数据结构",
"汇编语言",
"高数",
"大学语文",
"毛概"};
while(true){
System.out.println("输入命令:1-按照名称查找图书;2-按照序号查找图书");
String book;
try {
//取得整型命令
int command = inputCommand();
//根据不同的命令进行不同的操作
switch (command) {
case 1://根据图书名称选择图书
book = getBookByName(books);
System.out.println("book:"+ book);
break;
case 2://根据图书序号选择图书
book = getBookByNumber(books);
System.out.println("book:"+ book);
break;
case -1://返回值为-1,说明输入有错误
System.out.println("命令输入错误!请根据提示输入数字命令!");
continue;
default://其他值的命令均认为是错误命令
System.out.println("命令输入错误!");
break;
}
} catch (Exception bne) {
bne.printStackTrace();
System.out.println(bne.getMessage());
// TODO: handle exception
continue;
}
}
}
}
异常链方法及注释如图↓
initCause包装异常抛给中层到时候上层调用getinit就能看到最底层的原因.异常链每一层都可以捕获异常
异常链的简单写法
异常链的举例
异常链
public void test1() throws DrunkException()//声明抛出异常
{
throw new DrunkException("sdvwvdw");//抛出异常
}
public void test2()
{
try{test1();//调用时会抛出异常}//捕获异常
catch(DrunkException e){
RuntimeException ex=new RuntimeException("SADFD");
ex.initCause(e);//包装成运行时异常
throw ex;
}//处理异常
}
替换RuntimeException ex=new RuntimeException(e);
一、RuntimeException newExc = new RuntimeException("司机一滴酒,亲人两行泪");
newExc.initCause(e);
throw newExc;
二、
Java中的异常链:把捕获的异常包装成新的异常,然后在新的异常添加对原始异常的引用,再把这个新异常抛出,就像链式反应,一个导致另一个。
https://blog.csdn.net/u012580143/article/details/66973653
e.printStrackTrace(); 作用是进行深层次的输出异常调用的流程 RunTimeException(); 这是运行时异常,是所有java虚拟机正常操作期间可以被抛出异常的父类!
newExc.initCause(e); 这是一种对异常的一种包装技巧。
initCause()的作用是保存原始的异常,当想要知道底层发生了什么异常的时候调用getCause()就能获得原始异常。
Java异常链:
类是可以继承异常 比如 extends Exception
initCause()方法:对异常来进行包装的,目的就是为了出了问题的时候能够追根究底。 举个例子,在底层会出现一个A异常,然后在中间代码层捕获A异常,对上层抛出一个B异常。如果在中间代码层不对A进行包装,在上层代码捕捉到B异常后就不知道为什么会导致B异常的发生,但是包装以后我们就可以用getCause()方法获得原始的A异常。这对追查BUG是很有利的。
e.printStrackTrace(); 作用是进行深层次的输出异常调用的流程 RunTimeException(); 这是运行时异常,是所有java虚拟机正常操作期间可以被抛出异常的父类!
newExc.initCause(e); 这是一种对异常的一种包装技巧。
initCause()的作用是保存原始的异常,当想要知道底层发生了什么异常的时候调用getCause()就能获得原始异常。
运行结果。
异常链的另一种写法
异常链
package com.imooc.test; public class ChainTest { 注释 test1():抛出“喝大了”异常 test2():调用test1(),捕获“喝大了”异常,并且包装成运行时 异常,继续抛出 main方法中,调用test2(),尝试捕获test2()方法抛出的异常 public static void main(String[] args){ ChainTset ct = new ChainTest(); try{ ct.test2(); }catch(Exception e){ e.printStackTrace(); } } public void test1() throws DrunkException{ throw new DrunkException("喝车别开酒!"); } public void test2(){ try{ test1(); }catch(DrunkException e){ RuntimeException newExc = new RuntimeException("司机一滴酒,亲人两行泪"); newExc.initCause(e); throw newExc; } } }
包装
抛出
包装
异常A被捕获后抛出了一个新的异常B,用initCause()来保存异常A的原始数据,捕获异常B后使用getCause(),来获取导致B异常的原因。
package com.cuit;
public class test {
/*** test1():抛出“喝大了”异常
* test2():调用test1(),捕获喝大了异常,并且包装成运行*时异常继续抛出
* main方法中调用test2()尝试捕获test2()方法抛出的异常
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
test tt = new test();
try {
tt.test2();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
public void test1() throws DrunkException{
throw new DrunkException("喝酒别开车!");
}
public void test2(){
try {
test1();
} catch (DrunkException e) {
// TODO Auto-generated catch block
RuntimeException newExc =
new RuntimeException("司机一滴酒,亲人两行泪");
newExc.initCause(e);
throw newExc;
}
}
}
package com.cuit;
public class test {
/*** test1():抛出“喝大了”异常
* test2():调用test1(),捕获喝大了异常,并且包装成运行*时异常继续抛出
* main方法中调用test2()尝试捕获test2()方法抛出的异常
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
test tt = new test();
try {
tt.test2();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
public void test1() throws DrunkException{
throw new DrunkException("喝酒别开车!");
}
public void test2(){
try {
test1();
} catch (DrunkException e) {
// TODO Auto-generated catch block
RuntimeException newExc =
new RuntimeException("司机一滴酒,亲人两行泪");
newExc.initCause(e);
throw newExc;
}
}
}