欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java Exception

程序员文章站 2022-07-15 12:54:30
...

Java Exception

java中在处理Exception中经常出现异常的丢失问题,比如下面的代码

package com.viashare.exception;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * Created by Jeffy on 15/04/13.
 */
public class FailExceptionMain {

    public static void main(String[] args) throws WrapperException {
        InputStream input = null;
        try{

            input = new FileInputStream("test.txt");

        } catch(IOException e){
            e.printStackTrace();
            throw new WrapperException(e);
        } finally {
            try{
                input.close();
            } catch(IOException e){
                throw new WrapperException(e);
            }
        }
    }

    static class WrapperException extends Exception{
        private Exception exception;

        public WrapperException(Exception exception) {
            this.exception = exception;
        }
    }
}

上面的例子中假设 test.txt 文件不存在的话,那么在第一个catch块中catch住这个异常,但是因为有finally块,所以在抛出异常之前,执行了input.close();,因为文件不存在,所以在执行 input.close() 时抛出NullPointerException,然而catch的是IOException 所以异常丢失,下面是输出的结果:


Exception in thread "main" java.lang.NullPointerException
    at com.viashare.exception.FailExceptionMain.main(FailExceptionMain.java:23)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
    

为了更好的处理类问题,我们需要认真的判断这个非空。

package com.viashare.exception;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * Created by Jeffy on 16/04/13.
 */
public class FailExceptionMain {

    public static void main(String[] args) throws WrapperException {
        InputStream input = null;
        try{

            input = new FileInputStream("test.txt");

        } catch(IOException e){
//            e.printStackTrace();
            throw new WrapperException(e);
        } finally {
            try{
                if(null!=input)
                    input.close();
            } catch(IOException e){
                throw new WrapperException(e);
            }
        }
    }

    static class WrapperException extends Exception{
        private Exception exception;

        public WrapperException(Exception exception) {
            this.exception = exception;
        }
    }
}

但即使这个异常处理也有问题。让我们假设文件存在,所以“input”引用现在指向一个有效的FileInputStream。我们还假装在处理输入流时抛出异常。该异常被捕获在catch(IOException e)块中。然后被包裹并重新抛出。在包裹的异常传播到调用堆栈之前,finally子句被执行。如果input.close()调用失败,并抛出IOException,那么它被捕获,包装和重新抛出。但是,当从finally子句抛出包装的异常时,再次忘记了从第一个catch块抛出的包装异常。它消失了只有从第二个catch块抛出的异常在调用堆栈中传播。

如您所见,失败的安全异常处理并不总是微不足道的。 InputStream处理示例甚至不是您可以遇到的最复杂的例子。 JDBC中的事务有更多错误的可能性。当尝试提交,然后回滚,最后当您尝试关闭连接时,可能会发生异常。所有这些可能的异常都应该由异常处理代码来处理,所以它们都不会抛出第一个异常消失。一种方法是确保抛出的最后一个异常包含以前抛出的所有异常。这样他们都可以向开发人员调查错误原因。这就是我们的Java持久化API Persister先生实现事务异常处理的方式。