1、异常运行流程
2、异常的产生
- 自动抛出异常:在程序运行时遇到不符合规范的代码结果时,会产生异常。
String str = null; System.out.println(str.getClass()); //报出NullPointerException
- 手动抛出异常:使用throw关键字
public void test(){ throw new NullPointerException("手动抛出空指针异常"); }
- 产生异常的结果:相当于return语句,会导致程序的异常终止。
3、处理异常的两种方式
- 使用 try{} catch(){} 语句捕捉处理异常
- 使用 throws 向上抛出异常
4、throw和throws关键字
- throw:用来手动抛出一个异常(可以是自定义异常)
public void test(String name){ if(name == null){ throws new NullPointerException(); } }
- throws:如果方法中不捕获异常,则把异常丢弃给调用此方法的调用者。
//可以抛出 检查时异常 和 运行时异常 public void test(int num) throws RuntimeException,IOException{ if(num==0){ throw new RuntimeException(); }else if(num==-1){ throw new IOException(); } }
5、受查异常(编译时)/运行时异常
- 受查异常(CheckedException)
编译时异常:必须处理,否则无法通过编译
- 运行时异常(RuntimeException)
运行时异常:可处理,可不处理,但发生异常可能导致程序终止
6、自定义异常
- 自定义受检异常:
//自定义一个编译时异常类 class MyException extends Exception{ MyException(){} MyException(String name){super(name);} }
- 自定义运行时异常:
//自定义一个运行时异常类 class MyRuntimeException extends RuntimeException{ MyRuntimeException(){} MyRuntimeException(String name){super(name);} }
7、子类父类抛出异常问题(详解)
-
方法重写的时候,如果父类没有抛出任何异常,那么子类只可以抛出运行时异常,不可以抛出编译时异常。
class FaTest{ public void eat(){} } class sonTest extends FaTest{ //父类方法中没有编译时异常,所以子类不能抛出编译时异常 /*public void eat() throws Exception { //编译报错 }*/ }
-
如果父类的方法抛出了一个异常,那么子类在方法重写的时候不能抛出比被重写方法申明更加宽泛的编译时异常。
class FaTest{ //父类抛出IOException编译时异常 public void eat() throws IOException{} } class sonTest extends FaTest{ //子类的不能抛出更宽泛的编译时异常 /*public void eat() throws Exception { //编译报错 }*/ }
-
子类重写方法的时候可以随时抛出运行时异常,包括空指针异常,数组越界异常等。
class FaTest{ //父类抛出NullPointerException空指针异常(运行时) public void eat() throws NullPointerException{} } class sonTest extends FaTest{ //子类可以随时抛出 运行时异常 public void eat() throws RuntimeException{ //正常编译 } }
-
总结:重写异常问题,针对的是编译时异常,而运行时异常子类可以随时抛出,并不受重写约束。