基础知识

1、异常是一种Exception类型的对象(异常是一种对象)
因为异常是对象,所以你catch住的也是对象,下面程序代码中catch的参数是Exception类型的ex引用变量
try {
} catch(Exception ex) { //Exception类型的对象可以是任何它的子类的实例
//尝试恢复
}
2、如果你的程序代码会抓住异常,那是谁把它抛出来的?

//有风险、会抛出异常的代码public void takeRisk() throws BadException {//必须声明它会抛出BadException
if(abandonAllHope) {
throw new BadException();//创建Exception对象并抛出
}
}
//调用该方法的程序代码
public coid crossFingers() {
try {
anObject.takeRisk();
} catch(BadException ae) {
System.out.println("Aaargh");
ex.printStackTrace();//如果无法从异常中恢复,至少也要使用printStackTrace()来列出有用的信息
}
}
举例:
public class Test {
int age;
public void getAge(int age) throws AgeException{//声明它会抛出AgeException
this.age = age;
if(age > 100) {
throw new AgeException();//创建AgeException对象并抛出
}
}
public static void main(String[] args) {
Test t = new Test();
t.getAge(200);//调用会抛出异常的方法
}
}
class AgeException extends Exception {//自定义异常AgeException继承Exception
//
}

异常是程序运行期间出现的,区别于程序编译期间的代码错误
3、为什么编译器不管RuntimeException
大部分RuntimeException都是因为程序逻辑问题,而不是以你所无法预测或防止的方法出现的
执行期间失败状况,你无法保证文件一直都在,你无法保证服务器不会死机,但是你可以确保程序
不会运行不合理的逻辑,例如对只有5项元素的数组取第八个元素的值。
4、try/catch块的控制流程

5、finally:无论如何都要执行的部分
/*
如果try/catch块有return指令,finally还是会执行,
流程会条到finally然后再回到return指令
*/
try {
turnOvenOn();
x.bake();
trunOvenOff();
} catch (BakingException ex) {
ex.printStackTrace();
trunOvenOff();
}
6、try/catch/finally/throw/throws实例:
public class Test {
public static void main(String[] args) {
String test = "yes";
try {
System.out.println("start try");
doRisky(test);
System.out.println("end try");
} catch(ScaryExteption ae) {
System.out.println("scary exception");
} finally {
System.out.println("finally");
}
System.out.println("end of main");
}
static void doRisky(String test) throws ScaryExteption {
System.out.println("start risky");
if("yes".equals(test)) {
throw new ScaryExteption();
}
System.out.println("end risky");//不再执行
return;//不再执行
}
}
class ScaryExteption extends Exception {}//ScaryExteption为自定义异常
String test = "yes"执行结果:
String test = "no"执行结果:
7、处理多重异常
多重方法可以抛出多个异常,但该方法的声明必须要含有全部可能的检查异常(若两个或两个异常的异常有共同的父类时,可以只声明该父类就行)
public class Laundry {
public void doLaundry() throws PantsException, LingerieException {
//可能抛出两个异常的程序代码
}
}
public class Foo {
public void () {
Laundry laundry = new Laundry();
try{
laundry.doLaundry();
} catch(PantsException pex) {
//恢复程序代码
} catch(LingerieException lex) {
//恢复程序代码
}
}
}
8、异常也是多态的
异常是对象,因此异常也能够以多态的方式来引用

9、可以用父类来处理所有的异常并不代表就应该这么做
把异常处理程序代码写成只有一个catch块以父型的Exception来捕获
try {
laundry.doLaundry();
} catch (Exception ex) {//恢复什么?这个会捕获所有的异常,一次你会搞不清楚哪里出错
//解决方案......
}
有多个catch块时要从小到大,不能把大篮子放在小篮子上面(否则会无法通过编译)

个人理解:下面例子中:当我们用父类捕获异常时(多个子类捕获效果一致)实际上在第一个异常抛出的时候就catch住了,而后程序就会执行恢复此问题的方法,程序结束。
我们不能用父类捕获异常是因为程序运行的时候,会根据捕获的不用异常执行不同的恢复该异常的方法,如果我们用父类捕获异常,那么只能写一个
异常的恢复方法,难以满足一个恢复方法恢复所有类型的异常
public class Test {
int age;
public void getAge(int age) throws Age1Exception, Age2Exception{
this.age = age;
if(age > 100) {
throw new Age1Exception();
}
if (age > 200) {//上面抛出异常后,该if语句也不再运行
throw new Age2Exception();
}
}
public static void main(String[] args) {
Test t = new Test();
try {
t.getAge(500);
}catch (Age1Exception ae) {//只能catch住Age1Exception
ae.printStackTrace();
}catch (Age2Exception ae) {//不运行
ae.printStackTrace();
}
}
/*效果同上面分别catch
public static void main(String[] args) {
Test t = new Test();
try {
t.getAge(500);
}catch (Exception ae) {
ae.printStackTrace();
}
}
*/
}
class Age1Exception extends Exception {}
class Age2Exception extends Exception {}

10、不想处理异常时。可以把它duck掉来避开(交给下一个调用的方法来处理)

(ducking只是在踢皮球,早晚还得有人来处理这件事,如果连main()也duck掉异常,程序可编译但是运行报错)

执行结果:


来源:https://www.cnblogs.com/wmjlh/p/7297575.html