概述的内容理解就好,对应应用层的内容需要掌握
异常概述
- 异常:非正常情况。
什么是异常?其实就是非正常情况,通俗的说,异常就是咱程序出现了错误。 Java中的 异常是一个很庞大的体系,要求你知道他的体系结构划分
异常 Throwable 分类
可以通过上图看到,对应Java体系中异常分为2大类:一个是异常(Exception),还有一个是错误(Error)。下面我们来分别看一下这两个内容和区别。
异常 Exception
第一个就是Exception,程序代码层级我们可以处理的异常内容。
- 合理的应用程序可能需要捕获的问题「可预料的问题」
比如
NullPointerException
空指针异常,你要是通过null
常量调用成员方法,程序就会报空指针异常。解决方案:就是在调用成员方法的时候加上判断,不让
null
调成员方法就可以了。
异常的处理方式
我们既然知道这个解决的思路了,下面我们就来看下在开发的代码中怎么处理这些异常。
有2种方式:一种呢就是业务逻辑代码自己捕获这个异常,然后自己处理;还有一种就是业务逻辑代码把这个异常抛出来,谁调用谁处理。
JVM默认的异常处理方式
我们前面代码出现问题,在代码层级我们都没有处理,只是JVM自己默认处理的。
JVM的默认处理方式就是将异常的信息打印到控制台上,然后终止程序,这就是为什么以前的代码出现报错信息,对应的代码就不会再继续往下执行的原因。
- 在控制台打印错误信息,并终止程序
我们需要处理的异常是Exception,如果我们不处理,那就由JVM来默认处理的,JVM处理的方式就是将异常信息打印到控制台显示出来并终止程序。
下面我们来看一个正常的代码块内容:
int a = 13;
System.out.println(a);
我们看到上面的内容可以正常打印输出,那这个时候我加上一些东西。
我们知道对应的被除数在数学里是不可以为0的,那我这里就让它除以0,看一下效果:
//被除数0
int b = 13/0;
System.out.println(b);
对应控制台显示异常信息:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at top.testeru.keywords.tryp.Test.main(Test.java:22)
- 控制台打印异常信息解释说明
ArithmeticException
:异常类型by zero
:异常原因Test.java:22
:包名.类名.方法 哪一行出现的错误
可以看到JVM处理的结果是在控制台显示报错信息,并且终止程序执行,因为我们看到后面的打印输出内容没有在控制台进行一个打印。
try…catch「finally」
- 捕获,自己处理
首先,我们来看第一个。就是自己捕获异常自己处理,用到的代码是:
try--catch-finally
(一)格式:
try {
//尝试执行的代码
}catch (Exception exception){
//Exception 异常类型
//... 出现可能异常之后的处理代码
}finally {
//里面的代码一定会执行,主要做资源回收关闭操作
}
(二)应用:
我们下面对上面报错代码进行一个try-catch异常处理,通过try-cath来处理异常。
try {
//尝试要执行的代码
int b = 13/0;
System.out.println(b);
}catch (Exception e){
//出现问题后的代码(解决方案)
System.out.println("被除数不能是0");
}
System.out.println("----最后打印内容----");
被除数不能是0
----最后打印内容----
可以看到对应的最后打印内容输出了,控制台也没有报错了,但是b的值还是没有打印,打印的是:catch里面的内容「被除数不能为0」
(三)特点:
- 处理完异常之后程序是会继续执行
(四)finally作用:
- 正常情况下,无论怎样finally代码块内容都会被执行
如果在
cath
代码里面进行一个return
语句,可以看到最后打印的内容没有了。说明执行完cath
的内容就直接return
了,代码不会再继续运行。那如果不管是有没有
return
我都想要去执行的最后打印内容,怎么解决呢?
就要用到我们前面写的finally
,就是无论怎样finally代码块里面的内容都会被执行。
代码如下:
try {
//尝试要执行的代码
int b = 13/0;
System.out.println(b);
}catch (Exception e){
//出现问题后的代码(解决方案)
System.out.println("被除数不能是0");
return;
}finally {
System.out.println("----最后打印内容----");
}
上面是对应
catch
代码块添加return效果,那如果代码不抛出异常,try代码块的内容return的时候,finally代码块的内容会被执行吗?
其实是一样的,无论是try-catch里面谁return,对应finally的代码块都会被执行。对应demo如下:
try {
//尝试要执行的代码
int b = 13;
System.out.println(b);
return;
}catch (Exception e){
//出现问题后的代码(解决方案)
System.out.println("被除数不能是0");
return;
}finally {
System.out.println("----最后打印内容----");
}
以上就是加不加finally代码块的区别;即使try--catch
里面有return
,finally
里面的代码在正常情况下都会被执行。
finally正常情况下一定会执行,那什么是非正常情况呢?
比如说正在执行的过程中,服务器突然断电了,那这就是非正常情况了,这种情况不管是什么代码都不会被执行了。
(五)执行流程:
先执行try里面的内容,看看有没有问题。如果没有异常直接执行finally有代码块中的内容 ,如果有问题,在报错的那行就会跳转到cath代码块中执行里面的内容,再执行finall代码块中的内容
- 执行try代码块
- 有异常:try代码块{异常代码}—->cath代码块—->finall代码块
- 无异常:try代码块—->finall代码块
throws
- 抛出,交给调用者处理
其实就是直接在方法后面加上throw并抛出异常就可以。
首先定义一个方法,方法内
(一)格式:
访问权限 返回值 方法名(形参) throws Exception{
}
(二)应用:
还是对上面报错的代码进行一个throws异常处理。
public class Test {
//抛出异常,交给调用者处理
public static void num() throws Exception{
int c = 13/0;
System.out.println("c:"+c);
}
public static void main(String[] args) throws Exception {
num();// throws Exception
//main函数直接抛出异常,对应的main函数异常抛给了JVM,因为main函数是JVM调用的
System.out.println("看看都执行了吗");
}
}
Exception in thread "main" java.lang.ArithmeticException: / by zero
at top.testeru.keywords.tryp.Test.num(Test.java:57)
at top.testeru.keywords.tryp.Test.main(Test.java:48)
可以看到对应的最后打印内容没有输出,控制台有报错了,main方法直接抛出异常给了JVM,让JVM进行的异常操作
(三)特点:
- 执行结束后,程序不再继续执行
(四)调用者处理异常方式:
同样调用者处理方法抛出异常方式有2种,一种就是上面我们演示的,直接在调用函数上抛异常,一层层的抛出,最后还是JVM去执行。
还有一种就是上面演示的第一种,在调用函数种把被调的方法使用try-catch进行异常的抛出。这样,try-cath抛出异常后程序会继续执行。
错误 Error
异常还有另外一个分类,就是Error。
- 合理的应用程序不应该试图捕获的问题「不可预料的问题」
当然程序如果出现了
Error
的错误,我们也解决不了。比如StackOverFlowError
内存溢出,
这个异常和代码没关系,代码都是正常,只是服务器的硬件上你的内存不够用了,就会报这个异常。解决方案,就是添加内存就可以了。
或者比如说服务器宕机、数据库崩溃,在登录页面对应就是访问不了,这些是Java程序员无法预料到的问题
总结
1.异常的概念
2.异常的分类