1. 异常概述
1.1异常:就是不正常。程序在运行时出现的不正常情况。其实就是程序中出现的问题。这个问题按照面向对象思想进行描述,并封装成了对象。因为问题的产生有产生的原因、有问题的名称、有问题的描述等多个属性信息存在。当出现多属性信息最方便的方式就是将这些信息进行封装。异常就是java按照面向对象的思想将问题进行对象封装。这样就方便于操作问题以及处理问题。
1.2出现的问题有很多种,比如角标越界,空指针等都是。就对这些问题进行分类。而且这些问题都有共性内容比如:每一个问题都有名称,同时还有问题描述的信息,问题出现的位置,所以可以不断的向上抽取。形成了异常体系。
1.3异常体系
--------java.lang.Throwable:
Throwable:可抛出的。
|--Error:错误,一般情况下,不编写针对性的代码进行处理,通常是jvm发生的,需要对程序进行修正。
|--Exception:异常,可以有针对性的处理方式
1.4 特点
1、无论是错误还是异常,它们都有具体的子类体现每一个问题,它们的子类都有一个共性,就是都以父类名作为子类的后缀名。
2、这个体系中的所有类和对象都具备一个独有的特点;就是可抛性。
可抛性的体现:就是这个体系中的类和对象都可以被throws和throw两个关键字所操作。
2. Throwable中的方法:
1、getMessage():获取异常信息,返回字符串。
2、toString():获取异常类名和异常信息,返回字符串。
3、printStackTrace():获取异常类名和异常信息,以及异常出现在程序中的位置,返回值void。
4、 printStackTrace(PrintStream s):通常用该方法将异常内容保存在日志文件中,以便查阅。
备注:jvm默认的异常处理机制,就是在调用printStackTrace方法,打印异常的堆栈跟踪信息
3. 异常的处理
处理方式有两种:1、捕捉;2、抛出。
1、对于捕捉:java有针对性的语句块进行处理。
try{
需要被检测的代码;
}
catch(异常类 变量名){
异常处理代码;
}
fianlly{
一定会执行的代码;//除非出现System.exit(0),jvm关闭
}
2、抛出:用throws向上抛出,交给上一级调用者处理,最终交给虚拟机,虚拟机也不能处理,强行中止。
4. 异常的分类
4.1异常分两种:
1、编译时被检查的异常,只要是Exception及其子类都是编译时被检测的异常。
2、运行时异常,其中Exception有一个特殊的子类RuntimeException,以及RuntimeException的子类是运行异常,这些异常是编译时不被检查的异常。
4.2编译时被检查的异常和运行时异常的区别:
编译被检查的异常在函数内被抛出,函数必须要声明,否编译失败。
声明的原因:是需要调用者对该异常进行处理。
运行时异常如果在函数内被抛出,在函数上不需要声明。
不声明的原因:不需要调用者处理,运行时异常发生,已经无法再让程序继续运行,所以,不让调用者处理的,直接让程序停止,由调用者对代码进行修正。
5. 异常处理的原则
1、函数内容如果抛出需要检测的异常,那么函数上必须要声明。
否则,必须在函数内用try/catch捕捉,否则编译失败。
2、如果调用到了声明异常的函数,那么try/catch,要么throws,否则编译失败。
3、什么时候catch,什么时候throws呢?
功能内容可以解决,用catch。
解决不了,用throws告诉调用者,由调用者解决。
4、一个功能如果抛出了多个异常,那么调用时,必须有对应多个catch进行针对性处理。
内部有几个需要检测的异常,就抛几个异常,抛出几个,就catch几个。
需要注意的是:try对应多个catch时,如果有父类的catch语句块,一定要放在下面。
如果放在第一个,父类被处理了,子类就不会被处理。
6. 自定义异常
6.1当开发时,项目中出现了java中没有定义过的问题时,这时就需要我们按照java异常建立思想,将项目的中的特有问题也进行对象的封装。这个异常,称为自定义异常。
6.2自定义异常的步骤:
1:定义一个子类继承Exception或RuntimeException,让该类具备可抛性。
2:通过throw 或者throws进行操作。
public class H_09ZiDingYiException
{
public static void main(String[] args)
{
Div2 d=new Div2();
try
{
intx=d.div(4, -1);
}
catch (FuShuExceptione)
{
System.out.print(e.toString());
}
}
}
class FuShuExceptionextends Exception
{
FuShuException()
{
super();
}
FuShuException(String msg)
{
super(msg);
}
}
class Div2
{
int div(inta,intb) throws FuShuException
{
if(b<0)
thrownew FuShuException("出现了除数是负数的问题");//手动通过throw关键字抛出一个自定义异常
returna/b;
}
}
结果:FuShuException: 出现了除数是负数的问题
7. throw和throws
1、throw定义在函数中,可以在try括号内也可以在catch括号内,明确地抛出一个异常对象。
需要注意的是,不要在throw语句下写其他语句,会因为不能执行到而报错。
2、throws定义在函数上,用于明确这个函数可能抛出的异常类,可以接多个异常类,用逗号隔开。
3、用throw抛出一个明确的异常,则函数上也必须用throws抛出同样或者其父类的异常。
例外:RuntimeExcepiton 可以中断程序而不在函数上抛出
4、在继承的情况下,如果父类没有抛出异常,那么子类只能使用try catch处理,不能抛出异常。
8. trycatch finally 代码块组合特点:
1. try catch finally
2. try catch(多个)当没有资源需要释放时,可以不用定义finally。
3. try finally 异常无法直接catch处理,但是资源必须关闭。
9. finally测试
public class Test6
{
public static void main(String[] args)
{
//调用exceptionTest方法接收返回值
int num=exceptionTest();
System.out.println(num);
}
public static int exceptionTest()
{
try
{
return 1;
}
catch(Exception e)
{
throw new RuntimeException("返回错误");
}
finally
{
System.out.println("finally执行了");
//return 2;finally语句中不要加return
}
}
}
结果:finally执行了
1
结果分析:
代码其实是按顺序执行的,在得到return的返回值后,finally语句也执行了。说明retrun不会影响finally语句的执行。
但因为返回值需要另外接收,所以只能接收后再打印出来。
需要注意的是:在finally语句中不要加return语句,一方面会覆盖前面代码return的结果,一方面会导致接收不到前面抛出的异常。