day 异常
异常的体系:
———-| Throwable 所以异常或者错误类的超类
————–|Error 错误 错误一般是用于jvm或者是硬件引发的问题,所以我们一般不会通过代码去处理错误的。
————–|Exception 异常 是需要通过代码去处理的。
——————| 运行时异常: 如果一个方法内部抛出了一个运行时异常,那么方法上 可以声明也可以不 声明,调用者可以以处理也可以不处理。
——————| 编译时异常(非运行时异常、受检异常): 如果一个方法内部抛出了一个编译时异常对象,那么方法上就必须要声明,而且调用者也必须要处理。
运行时异常: RuntimeException以及RuntimeException子类 都是属于运行时异常。
疑问: 为什么java编译器会如此严格要求编译时异常,对运行时异常如此宽松?
运行时异常都是可以通过程序员良好的编程习惯去避免,所以java编译器就没有严格要求处理运行时异常。
首先要了解Throwable里的常用方法,在eclipse常用的自动生成try catch的语句中,总是使用了e.printStackTrace,但是不清楚到底怎么用或者指代什么意思,只知道是描述了异常的详细信息, 之前看过的视频都很笼统, 也没有深究过,大概只是知道这么一个格式, 钟老师的讲解很仔细。这里做一下笔记
Throwable常用的方法:
toString() 返回当前异常对象的完整类名+病态信息(Message)。
getMessage() 返回的是创建Throwable传入的字符串信息。
printStackTrace() 打印异常的栈信息。
如何理解这个Message呢? 翻开API查看Throwable类我们发现有一个构造方法可以Throwable(String Message);看到这里我们就清楚了,如果是jvm帮我们自动抛出的异常是没有message的,这时的值是Null。
如何理解printStackTrace, 异常的栈信息呢?
用以下代码进行一个测试
class Demo8
{
public static void main(String[] args)
{
test();
}
public static void test(){
//
Throwable t = new Throwable("sb");
t.printStackTrace();
}
}
分析结果:
首先打印toString的结果,然后换行依次打印错误的栈信息,运行时首先执行test方法,在12行的test方法中出现了这个异常,但是因为没有处理,继而导致了第7行的test(); 调用方法语句也出现了异常。这样便于我们追根溯源
异常的处理方式
1: 捕获处理
即用try catch语句
捕获处理要注意的细节:
1. 如果try块中代码出了异常经过了处理之后,那么try-catch块外面的代码可以正常执行。
2. 如果try块中出了异常的代码,那么在try块中出现异常代码后面的代码是不会执行了。
3. 一个try块后面是可以跟有多个catch块的,也就是一个try块可以捕获多种异常的类型。
4. 一个try块可以捕获多种异常的类型,但是捕获的异常类型必须从小到大进行捕获,否则编译报错。
注意第四点:实际上jvm是每次运行一句try中的语句, 就去寻找每一个catch是否有对应。并且是严格按照顺序从上往下的。如果先捕获大异常,则捕获具体异常的语句得不到执行。
2:抛出处理
抛出处理要注意的细节:
1. 如果一个方法内部抛出了一个异常对象,那么throw语句后面的代码都不会再执行了(一个方法遇到了throw关键字,该方法也会马上停止执行的)。
2. 在一种情况下,只能抛出一种类型异常对象。
throw 与throws两个关键字:
1. throw关键字是用于方法内部的,throws是用于方法声声明上的。
2. throw关键字是用于方法内部抛出一个异常对象的,throws关键字是用于在方法声明上声明抛出异常类型的。
3. throw关键字后面只能有一个异常对象,throws后面一次可以声明抛出多种类型的 异常。
自定义异常类
java提供的异常类虽然多,但是依然不能满足所有的需要。如果要创建一个专属的异常,我们需要创建一个类,继承Throwable类即可。当然我们也可以重写构造方法,和常用方法。
那么这个自定义异常类如何使用呢?要使用必定要抛出,问题是我们如何抛出
① 直接用在方法上if语句抛出
② 将可能抛出异常的语句封装成一个方法,并让这个方法throws 我们创建的异常。然后调用这个方法即可。
class NoMoneyException extends Exception {
public NoMoneyException(String message){
super(message);
}
}
class Demo3
{
public static void main(String[] args)
{
//System.out.println("Hello World!");
try{
eat(9);
}catch(NoMoneyException e){
e.printStackTrace();
System.out.println("跟我洗碗一个月!!");
}
}
public static void eat(int money) throws NoMoneyException{
if(money<10){
throw new NoMoneyException("吃霸王餐");
}
System.out.println("吃上了香喷喷的地沟油木桶饭!!");
}
}