文章目录
1. Java的异常处理机制
异常是指程序执行的非正常的情况。Java通过面向对象的方式对异常进行处理,Java把异常按照不同的类型进行分类,并提供了良好的接口。Java把所有非正常的情况分为两种:异常(Exception)和错误(Error ),它们都继承Throwable类。Throwable类是所有异常类的父类。
1.1 Error
表示编译时或者系统错误,如虚拟机相关的错误,OutOfMemoryError等,Error是无法处理的。
1.2 Exception
Exception能被程序处理,Exception分为两类:RuntimeException
(运行时异常)和CheckedException
(可检查的异常)
(1)RuntimeException(运行时异常)
RuntimeException类及其子类异常,如NullPointerException
(空指针异常)、IndexOutOfBoundsException
(下标越界异常)等,这些异常是不可查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
(2)CheckedException
(可检查的异常)
RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。
1.3 Error和Exception的区别
Java把所有的非正常的情况分为两种:异常(Exception)和错误(Error ),它们都继承Throwable类。Error错误,一般是指与虚拟机相关的问题,如系统崩溃、虚拟机错误、动态链接失败等,这种错误无法恢复或不可能捕获,将导致应用程序中断。通常应用程序无法处理这些错误,因此应用程序不应该试图使用catch块来捕获Error对象。在定义该方法时,也无须在其throws子句中声明该方法可能抛出Error及其子类。
2. Java的异常处理
Java的异常处理主要依赖于:try、catch、finally、throw、throws五个关键字,关键字作用如下
try
关键字后紧跟一个花括号括起来的代码块,简称try块,用来放置可能引发异常的代码catch
关键字后跟一个异常类型和一个代码块,用于表明该catch块用于处理这种类型异常的代码块finally
块用于回收在try块里打开的物理资源,异常机制会保证finally块总被执行throw
关键字用于抛出一个实际的异常,可以单独作为语句使用throws
关键字主要在方法签名中使用,用于声明该方法可能抛出的异常
完整的Java异常处理语法结构如下:
try{
//业务处理代码
......
}catch(异常种类1 异常对象){
//异常处理块1
......
}catch(异常种类2 异常对象){
//异常处理块1
......
}
finally{
//资源回收块
......
}
注意::异常处理语法结果中只有try块是必需的,没有try块,则不能有后面的catch块和finally块;catch块和finally块都是可选的,但catch块和finally块至少出现其一,也可以同时出现;可以有多个catch块,捕获父类异常的catch块必须位于捕获子类异常的后面(先处理小异常,再处理大异常),否则将出现编译错误。多个catch块(多异常捕获)必须位于try块之后,finally块必须位于所有的catch块之后。
2.1 throw和throws的区别
- throw一般出现在方法内部,用于抛出一个异常,throws一般出现在函数声明的头部
- throw是具体向外抛出的动作,所以它抛出的是一个异常实体类。若执行了throw一定是抛出了某种异常
- throws 声明可能抛出的异常,然后交给上层调用它的方法程序处理
2.2 try-catch-finally-return执行顺序
- 如果不发生异常,不会执行catch块部分;
- 不管有没有发生异常,finally块都会执行到;
- 即使try块和catch块中有return时,finally块仍然会执行;
- finally块如果有return,就不会执行try块或者catch块中的return了;
- finally是在try块或catch块中return后面的表达式运算完后再执行的。(此时并没有返回运算后的值,而是先把要返回的值保存起来,若finally中无return,则不管finally中的代码怎么样,返回的值都不会改变,仍然是之前保存的值),该情况下函数返回值是在finally执行前确定的)
3. 常见的异常
NullPointerException
空指针异常ClassNotFoundException
指定类找不到异常IndexOutOfBoundsException
数组下标越界异常IllegalArgumentException
方法传递参数错误SQLException
SQL异常NoSuchMethodException
方法不存在异常
4. 访问异常信息的方法
可以通过访问catch块的异常形参获得。当Java运行时决定调用某个catch块来处理该异常信息时,会将异常对象赋给catch块后的异常参数,程序可通过该参数来获得异常的信息。
异常对象包含了如下几个常用方法:
getMessage()
:返回该异常的详细描述字符串printStackTrace()
: 将该异常的跟踪栈信息输出到标准错误输出printStackTrace(PrintStream s)
:将该异常的跟踪栈信息输出到指定输出流getStackTrace()
:返回该异常的跟踪栈信息
代码测试如下:
public class Exception01 {
public static void main(String[] args) {
try {
System.out.println(5/0);
}catch(Exception e) {
e.getMessage();
e.printStackTrace();
}
}
}
运行输出如下:
java.lang.ArithmeticException: / by zero
at Exception.Exception01.main(Exception01.java:8)
5. 自定义异常
自定义异常通常是定义一个类继承Exception类或其子类
。自定义异常的好处:
- Java提供的异常体系不可能预见所有的错误;
- 业务开发中,使用自定义异常,可以让项目代码更加规范,也便于管理;
下面是一个自定义异常的例子:
/**
* 实现自定义异常
*/
class MyException extends RuntimeException{
public MyException() {
super();
}
public MyException(String message) {
super(message);
}
}
public class MyExceptionTest {
public void test01(int a) {
try {
if(a == 1) {
throw new MyException("传入参数为1异常");
}
} catch (MyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
new MyExceptionTest().test01(1);
}
}
运行之后结果如下:
Exception.MyException: 传入参数为1异常
at Exception.MyExceptionTest.test01(MyExceptionTest.java:23)
at Exception.MyExceptionTest.main(MyExceptionTest.java:33)
6. try-with-resources
try-with-resources,是Java7提供的一个新功能,它用于自动资源管理。它允许在try关键字后跟一对圆括号,圆括号可以声明、初始化一个或多个资源,多个资源之间以;
相隔,此处的资源是指那些必须在程序结束后显示关闭的资源(比如数据库连接、网络连接等),try语句在执行结束之后自动关闭这些资源。
- try-with-resources保证了每个声明了的资源在语句结束的时候会被关闭
- 为了保证try语句可以正常关闭资源,这些资源实现类必须实现
AutoCloseable
或Closeable
接口,实现这两个接口必须实现close()
方法。
public static void main(String[] args) throws FileNotFoundException, IOException {
try(//声明、初始化两个可关闭的资源,try语句会关闭这两个资源
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
PrintStream ps = new PrintStream(new FileOutputStream("a.txt"))){
//使用两个资源
System.out.println(br.readLine());
ps.println("xingze");
}
}
注: 自动关闭资源的try语句相当于包含了隐式的finally块(这个finally块用于关闭资源),因此这个try语句可以既没有catch块,也没有finally块。