这节课来学习异常的抛出和捕捉。
首先,什么叫抛出异常?代码解释。
算了,常用异常类以后看到了再讲。
接下来所有编译时异常类我们就直接抛Exception,运行时异常抛RuntimeException
Demo1:
//我们选择继续抛出
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
exceptionThrowTest(a); //因为exceptionThrowTest方法是选择向外层抛异常,所以异常会被抛出到这一层,这个时候我们还是要选择捕获或者继续抛出
}
//先来写个方法吧
//向外抛出异常,这是一个声明,表明这个方法里抛出的异常最后会向外层抛
//什么叫外层呢?调用这个方法的那一层就叫这个方法的外层
public static void exceptionThrowTest(int a) throws Exception
{
if (a<0)
{
//抛出异常
throw new Exception("传入的参数不可以为负数");//这里报红,说明编译时异常必须被显示抛出或捕获
}
}
输入:
-2
输出:
Exception in thread "main" java.lang.Exception: 传入的参数不可以为负数
上节课说过,如果最外层没有捕获异常,程序会直接停止运行并打印异常信息
异常信息的结构就是:
异常名+在哪里出异常+异常全类名: 异常里的detailMessage属性
源码摘取:
public Exception(String message) {
super(message);
}
public Throwable(String message) {
fillInStackTrace();
detailMessage = message;
}
可以看到输出的就是我们传给Exception构造器的那个字符串参数
接下来看运行时异常
Demo2:
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
runtimeExceptionThrowTest(a);
}
public static void runtimeExceptionThrowTest(int a)
{
if (a<0)
{
//抛出异常
throw new RuntimeException("传入的参数不可以为负数");//这里报红,说明编译时异常必须被显示抛出或捕获
}
}
输入:
-2
输出:
Exception in thread "main" java.lang.RuntimeException: 传入的参数不可以为负数
结论:运行时异常的抛出可以不必被显示捕获或抛出,如果不被显示捕获和抛出,默认向外层抛出
接下来看异常的捕获:
异常的捕获需要用到try-catch语法结构,还是直接看代码:
被try/catch包裹
try-catch语法:
try{
可能会抛出异常的代码片段
}catch(异常类 变量名){
处理代码
}
Demo 3:
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
//我们来手写一下
try{
//可能会抛出异常的片段
exceptionThrowTest(a);
}catch(Exception e){
System.out.println("出异常啦");
}
System.out.println("异常已经被捕获并且处理啦,程序还是会继续运行,不会终止的哦");
}
输入:
-3
输出:
出异常啦
异常已经被捕获并且处理啦,程序还是会继续运行,不会终止的哦
结论:
Demo 4:
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
//我们来手写一下
try{
runtimeExceptionThrowTest(a);
exceptionThrowTest(a);
}catch (RuntimeException e){
System.out.println("这里被RuntimeException捕获啦");
e.printStackTrace(); //输出异常信息
} catch(Exception e){
System.out.println("出异常啦");
e.printStackTrace(); //输出异常信息
}
//runtimeExceptionThrowTest(a);
System.out.println("异常已经被捕获并且处理啦,程序还是会继续运行,不会终止的哦");
}
public static void exceptionThrowTest(int a) throws Exception
{
if (a>0)
{
//抛出异常
throw new Exception("传入的参数不可以为正数");//这里报红,说明编译时异常必须被显示抛出或捕获
}
}
public static void runtimeExceptionThrowTest(int a)
{
if (a<0)
{
//抛出异常
throw new RuntimeException("传入的参数不可以为负数");//这里报红,说明编译时异常必须被显示抛出或捕获
}
}
输入:
2
输出:
出异常啦
java.lang.Exception: 传入的参数不可以为正数
at helloworld.exception.ExceptionTeach.exceptionThrowTest(ExceptionTeach.java:34)
at helloworld.exception.ExceptionTeach.main(ExceptionTeach.java:14)
异常已经被捕获并且处理啦,程序还是会继续运行,不会终止的哦
输出顺序应该是上面这样的,idea输出的顺序不太符合我们预想的结果哈,不过内容输出的没错,只是顺序问题而已,这个应该是idea的问题
分析:
输入2,抛出的是Exception异常,所以不会捕获RuntimeException异常,也就不会输出”这里被RuntimeException捕获啦”
输入:
-1
输出:
这里被RuntimeException捕获啦
java.lang.RuntimeException: 传入的参数不可以为负数
at helloworld.exception.ExceptionTeach.runtimeExceptionThrowTest(ExceptionTeach.java:43)
at helloworld.exception.ExceptionTeach.main(ExceptionTeach.java:13)
异常已经被捕获并且处理啦,程序还是会继续运行,不会终止的哦
分析:
这个显然捕获的是RuntimeException啦,而且根据输出信息可以看出异常只会被捕获一次,因为处理Exception异常的代码并没有被执行
注意:
差点忘记说了,这里的是throws,表明可以抛出多个异常,多个异常用逗号隔开
throws抛出的异常不一定会被抛出,throws只是负责向外抛这个方法捕获到的异常,不负责判断这个异常到底有没有被捕获到,所以throws后面可以随便写
但是,throws后面必须包含本方法可能被抛出的异常,除非这个异常在本方法内已经被捕获了或者这个异常是运行时异常
这个就是异常的抛出和捕获。