java异常处理之try...catch...finally详解

原创 2017年07月17日 22:11:51

    异常处理机制已经成为判断一门编程语言是否成熟的标准之一,其对代码的健壮性有很大影响。一直以来异常处理使用不是很得心应手,今天对异常进行了较为深入的学习,这篇主要是对try…catch…finally的一个总结。

一.java继承体系

    Java语言为异常处理提供了丰富的异常类,这些类之间有严格的继承关系。如图:
这里写图片描述
从图中我们可以看出,所有的类都是继承于Throwable这个父类,java将所有的非正常情况分为两种:Error(错误)和Exception(异常),Error错误一般是于虚拟机相关的问题,如系统崩溃、虚拟机错误、动态链接失败等,这种错误是无法恢复或不可能捕获的,而我们能处理的是Exception类下的错误。Exception则分为两大类,RuntimeException(运行时异常)和其他异常(Checked异常),其他异常(Checked异常)是各种形式的编译错误,是我们必须显示处理才可以通过变异的;而运行时错误顾名思义就是程序已经通过了编译,在运行时出现的错误,若是对这些异常置之不理会导致程序停止运行、占用资源无法释放甚至导致系统崩溃。

二.java异常处理机制及实现方法

  1. 主要依赖于try、catch、finally、throw和throws这五个关键字。(throw和throws本篇不涉及)
  2. try…catch…finally处理机制:try关键字后跟一个花括号栝起的代码块(即使该代码块只有一行也不能省略花括号),简称try块。catch对应异常类型和代码块,用于表明更改catch块用于处理该种类型的异常。一个try块后可以跟多个catch块。在catch块后还可以跟一个finally块,finally块用于回收在try块里打开的资源。
    这样讲过于抽象,那我们看几个例子:
    e.g.1 try…catch语句块
/*功能:对输入的两个数进行相除运算*/
public class DivTest {
    public static void main(String[] args) {
        try {
            int a = Integer.parseInt(args[0]);
            int b = Integer.parseInt(args[1]);
            int c = a/b;
            System.out.println("您输入的两个数相除的结果是:" + c);
        } catch(IndexOutOfBoundsException ie) {
            System.out.println("数组越界");
        } catch(NumberFormatException ne) {
            System.out.println("数字格式异常");
        }  catch(ArithmeticException ae) {
            System.out.println("算术异常");
        }  catch(Exception e) {
            System.out.println("未知异常");
        } 
    }
}

    以上代码我们看到,对不同的异常情况作了不同的处理:输入参数不够会发生数组越界异常、输入参数不是数字发生数字格式异常、若输入第二个数是0,则发生除0异常,调用算术异常进行处理、出现其他异常时那么该异常对象必定是Exception类或其子类的实例,java调用Exception类对其进行处理,前三种异常类均是RuntimeException的子类。在使用try…catch语句块时需要知道或注意以下几点:
 1) 处理过程:代码在执行的时候,进入try块,若是在try块中出现了异常,系统会自动生成一个一场对象,该对象被提交给java运行时环境,这就是异常的抛出;在java运行时环境收到异常对象时则把该对象交给catch块处理,这个过程叫做异常的捕获;若找到相应的catch块就执行catch块中的代码,若没有找到,则运行时环境终止,程序也退出。
 2) 执行一次try块只执行一个catch块
 3) 有多个catch块并有继承关系的情况下必须先写子类后写父类(即先捕获小异常再捕获大异常),若写反在编译时就会报错
 4) Java7提供的多异常捕获:在Java7之前,每一个catch块只能捕获一种异常,但从java7开始,一个catch块可以捕获多种类型的异常。在使用多异常捕获应注意两点:
  (1) 多种异常之间用竖线( | )隔开
  (2) 多种异常对象被final隐式修饰,因此程序不能对其重新赋值
 以下代码是多异常捕获的例子:
 e.g.2

/*多异常捕获*/
public class MultiExceptionTest {
    public static void main(String[] args) {
        try {
            int a = Integer.parseInt(args[0]);
            int b = Integer.parseInt(args[1]);
            int c = a/b;
            System.out.println("您输入的两个数相除的结果是:" + c);
        } catch(IndexOutOfBoundsException|NumberFormatException|
        ArithmeticException ie) {
            System.out.println("数组越界或数字格式异常或算术异常");
            ie = new ArithmeticExcrption("test");   //①
        } catch(Exception e) {
            System.out.println("未知异常");
            e = new RuntimeException("test");   //②
        } 
    }
}

可以看出,以上代码中,①号代码是错误的,因为ie是被final隐式修饰的对象,②号代码是正确的
  3. 使用finally回收资源:有些时候我们在try块中打开了一些物理资源(例如数据库链接、网络连接和磁盘文件等),这些资源都应进行显示回收。有人说java不是有垃圾回收机制吗?java的垃圾回收机制是自动回收堆内存中对象所占用的内存,而物理资源是不会自动回收的。
finally重点学习以下几点:
 1) 执行过程以及引入finally的原因:finally最后执行并且最后执行,物理资源回收放在finally块中的原因就是finally块一定会被执行。相反,若是放在try块中,在执行之前就出现异常则跳转至catch块中,则回收资源的代码不会被执行;同样的,若是放在catch块中,若不发生异常,那么catch块就不会被执行
 2) 若是在catch快中有return语句,则先执行完finally中的程序后再回到catch块中并执行return语句
 3) 若是在finally中有return语句,那么try块和catch块中的return语句都会失效,不会被执行
 4) 若在catch块中强制退出虚拟机,如使用System.exit(1)语句,则会直接退出程序,finally也不会得到执行
  e.g.3

/*该类功能:打开a.txt文件,在finally块中对资源进行回收*/
/* 对代码中一些方法的解释:
 * 所有异常都包含以下几种访问异常信息的常用方法:
 * getMessage():返回该异常的详细描述字符串
 * printStackTrace():将该异常的跟踪栈信息输出到标准错误输出
 * printStaceTrace(PrintStack s):将该异常的跟踪栈信息到执行输出流
 * getStackTrace():返回该异常的跟踪栈信息
 */
public class FinallyTest {
    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("a.txt");
        }catch(IOException ioe) {
            System.out.println(ioe.getMessage());
            return;           //①
            System.exit(1);   //②
        }finally {
            if(fis != null) {
                try{
                    fis.close();
                }catch(IOException ioe) {
                    ioe.printStackTrace();
                }
            }
            System.out.println("执行finally块里的资源回收!");
        }
    }
}

注释掉②号代码运行以上程序,我们看到的结果是:

a.txt (系统找不到该文件。)
程序已经执行了finally里的资源回收!

注释掉①号代码运行以上程序,我们看到的结果是:

a.txt (系统找不到该文件。)

  4. 嵌套
例如e.g.3代码所示,finally块中还嵌套了一个try…catch语句块,这种在try块、catch块或finally块中包含完整的异常处理流程的情形被称为异常的嵌套。一般对嵌套深度没有限制,但是层次太深的嵌套会降低可读性。
  5.Java7的自动关闭资源的try语句:
  在java7之前,我们必须像e.g.3中的代码一样手动关闭文件,回收资源。在Java7中增强了try语句的功能,它允许在try关键字后紧跟一对圆括号,圆括号可以声明、初始化一个或多个资源,此处的资源指的是那些必须在程序结束时显示关闭的资源,try语句在该语句结束时自动关闭这些资源。这些资源实现类必须实现AutoCloseable或Closeable接口,实现这两个接口就必须实现close()方法。
注:Closeable是AutoCloseable接口的子接口,Closeable接口里的close()方法声明抛出了IOException,因此它的实现类在实现close()方法时只能声明抛出IOException或其子类;AutoCloseable接口里的close()方法声明抛出了Exception,因此它的实现类在实现close()方法时能抛出任何异常。Java7几乎把所有的“资源类”(包括文件IO的各种类、JDBC编程的Connection、Statement等接口)进行了改写,改写后的资源类都实现了AutoCloseable或Closeable接口
  e.g.4

/*使用自动回收资源的try语句*/
public class AutoCloseTest {
    public static void main(String[] args) throws IOException {
        try(
        //声明、初始化两个可关闭的资源,try语句会自动关闭这两个资源
        BufferedReader br = new BufferedReader(
        new FileReader("AutoCloseTest.java"));
        PrintStream ps =  new PrintStream(
        new FileOutputStream("a.txt"))) {
            //使用两个资源
            System.out.println(br.readLine());
            ps.println("自动关闭资源的try语句")
        }
    }
}

以上try语句块后的圆括号中声明、初始化了两个IO流,由于BufferedReader、PrintStream都实现了Closeable接口,所以try语句会自动关闭它们。自动关闭资源的try语句块相当于包含了隐式的finally块用于关闭资源,这个try语句可以没有catch块也可以没有finally块,大大减少了代码的长度。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

try_catch_finally异常处理java

  • 2013年06月11日 23:25
  • 4.36MB
  • 下载

Java异常处理throws,throw关键字try,catch,finally模块

ThrowableThrowable是所有的错误和异常的超类,有两大实例 Error 一般不处理,由JVM抛出 Exception 可预测可处理 —–编译时异常 :只要是Exception和其...

java的异常处理机制(try catch finally)

1 引子 try…catch…finally恐怕是大家再熟悉不过的语句了,而且感觉用起来也是很简单,逻辑上似乎也是很容易理解。不过,我亲自体验的“教训”告诉我,这个东西可不是想象中的那么简单、听话。...

java的异常处理机制(try…catch…finally)

2.1 相关概念 例外是在程序运行过程中发生的异常事件,比如除0溢出、数组越界、文件找不到等,这些事件的发生将阻止程序的正常运行。为了加强程序的鲁棒性,程序设计时,必须考虑到可能发生的异常事件并...

JAVA异常处理机制的个人理解(try catch throw finally)

搜到了这篇文章 ,下面说下我自己的问题与理解。 我看完程序给出的输出是: i=2 i=1 testEx2, catch exception testEx2, finally; ret...

Java的异常处理——try-catch-finally-throw-throws

大一大二写了写了两年C++,没有使用过异常处理机制。现在大三上学期学Java,我要彻底弄清楚异常处理是怎么弄的。...

Java异常处理( try catch finally throw throws exception error)

Java异常处理机制当程序中抛出一个异常后,程序从程序中导致异常的代码处跳出,java虚拟机检测寻找和try关键字匹配的处理该异常的catch块,如果找到,将控制权交到catch块中的代码,然后继续往...

java关于异常处理只使用try-finally而不使用catch

1. 前言:通常我们在异常处理的时候一般就使用try…catch,try { // 需要处理的代码段 } catch(Exception e) { // 异常处理方法 } 更加好一些的...
  • Ink4T
  • Ink4T
  • 2017年08月07日 23:32
  • 4700

java:异常处理机制 try-catch-throw-finally

try:try{ int i = 1/0; }catch(Exception e){ ........ } 一个计算的话,如果除数为0,则会报错,如果没有try的话,程序直接崩溃。用try的...

Java异常处理机制以及try-catch-finally-return执行顺序

一、异常:在Java语言中,将程序执行中发生的不正常情况称为“异常”,异常是一种对程序运行过程中发生错误时进行通知的机制。如:网络连接失败、用户输入错误或打开文件失败等。异常以对象的形式出现,不同的异...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java异常处理之try...catch...finally详解
举报原因:
原因补充:

(最多只允许输入30个字)