1、throws与throw关键字
1.1 throws 关键字
在定义一个方法的时候通常可以用throws关键字声明,使用throws声明的方法表示此方法不处理异常,由此方法的调用者处理。
throws使用格式
public 返回值类型 方法名称(参数列表…) throws 异常类 {}
结合具体例子来看,还是用两数相除求商的例子
class Math{
public int div(int i, int j)throws Exception{ // 定义除法方法,如有异常交给调用处处理
int result = i/j; // 两数相除可能出现异常
return result;
}
}
public class ThrowsDemo {
public static void main(String[] args) {
Math m = new Math();
try{
System.out.println("除法操作" + m.div(10,0));
} catch (Exception e) {
e.printStackTrace(); // 打印异常
}
}
}
// 运行结果:
java.lang.ArithmeticException: / by zero
at Math.div(ThrowsDemo.java:7)
at ThrowsDemo.main(ThrowsDemo.java:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
可以看到,在div()方法声明的时候用了throws关键字,方法体里没有去处理异常,而是在调用它的主方法里再去处理,那如果主方法也继续使用throws声明,那会怎么样?
class Math{
public int div(int i, int j)throws Exception{ // 定义除法方法,如有异常交给调用处处理
int result = i/j; // 两数相除可能出现异常
return result;
}
}
public class ThrowsDemo {
public static void main(String[] args) throws Exception {
Math m = new Math();
System.out.println("除法操作" + m.div(10, 0));
}
}
// 运行结果:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Math.div(ThrowsDemo.java:7)
at ThrowsDemo.main(ThrowsDemo.java:15)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
在主方法中使用了throws关键字,那么方法体中也不用再处理异常,而是交给更大一级的调用者处理,是谁呢?对了,就是JVM,所有的处理都由JVM来完成。
1.2 throw关键字
与throws关键字不同,使用throw关键字可以直接抛出一个异常,抛出的时候直接抛出异常类的实例化对象。
在异常处理中,try语句要捕获的是一个异常对象,那么该对象也可以自己抛出。
public class ThrowDemo {
public static void main(String[] args) {
try{
throw new Exception("自己抛自己玩");
}catch (Exception e){
System.out.println(e);
}
}
}
// 运行结果:
java.lang.Exception: 自己抛自己玩
1.3 实战 throws与throw的应用
实际开发中,try… catch … finally 、throw、throws一起使用的场景比较多。
例如现在要设计一个相除的方法,在开始的时候打印“方法开始”信息,结束的时候打印“方法结束”信息,中间有异常单独交给调用方法的地方处理
class Math{
public int div(int i, int j) throws Exception {
System.out.println("********** 计算开始 *********");
int result = 0;
try {
result = i / j;
} catch (Exception e) {
throw e; // 这里直接向外抛出异常,由调用处来处理
} finally {
System.out.println("********** 计算结束 *********");
}
return result;
}
}
public class ThrowDemo {
public static void main(String[] args) {
Math m = new Math();
try{
System.out.println("除法操作:" + m.div(10,0));
}catch (Exception e){
System.out.println("异常产生:" + e);
}
}
}
// 运行结果:
********** 计算开始 *********
********** 计算结束 *********
异常产生:java.lang.ArithmeticException: / by zero
思考:
这里要求在调用出处理异常,因此需要使用throws关键字声明div方法,而在div方法和main主方法里都加了try … catch语句,在div方法里的的catch语句直接throw了异常,由调用它的main方法处理,main方法里的catch捕获到并且处理。
下面是程序的执行过程
如果我们在div方法里没有用throw抛出异常,而是直接打印异常,那运行结果会是怎样?
class Math{
public int div(int i, int j) throws Exception {
System.out.println("********** 计算开始 *********");
int result = 0;
try {
result = i / j;
} catch (Exception e) {
e.printStackTrace(); // 这里不向外抛出异常,打印异常
} finally {
System.out.println("********** 计算结束 *********");
}
return result;
}
}
public class ThrowDemo {
public static void main(String[] args) {
Math m = new Math();
try{
System.out.println("除法操作:" + m.div(10,0));
}catch (Exception e){
System.out.println("异常产生:" + e);
}
}
}
// 运行结果:
java.lang.ArithmeticException: / by zero
********** 方法开始 *********
at Math.div(ThrowDemo.java:10)
********** 方法结束 *********
at ThrowDemo.main(ThrowDemo.java:24)
除法操作:0
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
2、Exception和RuntimeException
2.1 两者的区别
- Exception 在程序中必须用try … catch 处理
- RuntimeException 可以不使用 try … catch 处理,但是如有有异常 ,在异常交给JVM处理。
一般为了保证程序的健壮性,还是建议在可能出现异常的地方用 try … catch 处理