throw关键字用于在某个语句处抛出一个异常,只要执行到这个语句就表示必定抛出异常。
throws关键字用于在方法处抛出一个或多个异常,这表示执行这个方法可能会抛出异常。
对于Exception类(非RuntimeException)的异常即已检查异常类,在调用时要么进行捕捉,要么继续向上级抛出。这类错误产生和处理的过程为:
方法f()内部的方法体的throw向上抛出给方法f();
方法f()的throws向上抛出抛给f()调用者;
方法调用者必须捕捉处理,或者不想捕捉就继续向上抛出;
每一级的调用者都不想捕捉而是一直向上抛出,则最后由java虚拟机报错:"未报告的异常错误XXXX必须对其进行捕获或声明以便抛出"。
以下是抛出异常的一个简单示例,抛出的是ArithmeticException异常,因为是RuntimeException类异常,因此从方法体内部throw抛出后,无需在方法定义处使用throws继续抛出。
public class EX { void f(int n) { // 或void f(int n) throws ArithmeticException {} if (n == 0) { throw new ArithmeticException("hello Exception!"); } else { System.out.println("right!"); } } public static void main(String[] args) { EX m = new EX(); m.f(1); m.f(0); // throw Exception } }执行结果:
right! Exception in thread "main" java.lang.ArithmeticException: hello Exception! //异常的信息 at EX.f(EX.java:4) //真实产生异常的地方 at EX.main(EX.java:13) //调用产生异常的地方所以,对于RuntimeException类异常来说,是否使用throws关键字并无影响。一般来说,Exception类异常但非RuntimeException才需要使用throws关键字,因为Exception类异常必须要被捕获并处理,而RuntimeException异常则无所谓。
例如将上面的ArimeticException改为FileNotFoundException,前者为Runtime类异常,而后者为Exception但非Runtime类异常,因此使用throw抛出后,必须在定义方法处也使用throws抛出错误。这一过程是"向上级抛出"的过程:"方法体内部抛出异常-->抛给方法本身"。
void f(int n) throws FileNotFoundException { if (n == 0) { throw new FileNotFoundException("hello Exception!"); //throw a new yichang duixiang } else { System.out.println("right!"); } }如果不使用throws关键字抛出错误,则将报错:
EX.java:6: 错误: 未报告的异常错误FileNotFoundException; 必须对其进行捕获或声明以便抛出 throw new FileNotFoundException("hello Exception!"); //throw a new yichang duixiang从方法f()抛出向上抛出给调用者后,调用者要么使用try-catch捕捉,要么继续向上抛出,否则报错。例如捕捉
import java.io.*; public class EX { void f(int n) throws FileNotFoundException { if (n == 0) { throw new FileNotFoundException("hello Exception!"); } else { System.out.println("right!"); } } public static void main(String[] args) { try { EX m = new EX(); m.f(0); } catch (FileNotFoundException e) { System.out.println(e); } System.out.println("out of try-catch"); } }如果不捕捉,则可以继续在方法处向上抛出:
public static void main(String[] args) throws FileNotFoundException { EX m = new EX(); m.f(0); } 抛出异常时的注意事项throw可以同时定义可能抛出的多种异常,尽管这些异常存在继承关系。这时在捕捉异常时,应该先捕捉子类,再捕捉父类。
例如FileNotFoundException是IOException的子类,可以同时:
throws FileNotFoundException,IOException捕捉时应先捕捉FileNotFoundException,再IOException。
try { ... } catch (FileNotFoundException e) { ... } catch (IOException e) { ... }在重写有throws子句的方法时,需要注意:
子类重写父类方法要抛出与父类一致的异常,或者不抛出异常
子类重写父类方法所抛出的Exception类异常不能超过父类的范畴
子类重写父类方法抛出的异常可以超出父类范畴,但超出的部分必须是RuntimeException类的异常