Java异常抛出专题

前言

对于编译性异常我们必须捕获或者抛出 ,否则程序无法编译成功,对于非编译性异常(运行时异常),这类异常可以编译成功但在运行的时候可能就会发生异常,常见的运行时异常主要有:ClassCastException、IndexOutOfBoundsException、NullPointerException、ArrayStoreException等,这类异常一般是程序逻辑错误引起的,在编写代码的时候应该规避这类异常的发生。

相关问题

1:如果当前代码块存在异常,应该采用抛出的方式or捕获方式?
2:针对潜在的运行时异常是否应该对其做处理?

判读采用抛出异常or捕获处理异常?

  • 1:抛出异常VS捕获异常

抛出异常:抛出异常后当前方法无法继续下去,会从当前方法跳出来,然后把问题交给上一级处理,通过throws关键字抛出异常

捕获异常:可以对异常进行处理或者继续抛出,通过try-catch关键字进行异常捕获,异常在catch中被处理后,可以继续向下执行。也可以在catch中通过throw方法继续向外抛出异常,此时不能继续向下执行。

  • 2:异常处理的三个原则:具体明确、及早抛出、延迟处理

具体明确:抛出与捕获异常的时候尽量明确异常的类型,这样才能根据不同的异常,提供不同的解决方案。

@SuppressWarnings("resource")
    public void readFile(String fileName){
        if(fileName==null){
            throw new IllegalArgumentException("fileName must not be null");
        }

        try {
            InputStream is= new FileInputStream(fileName);
            is.read();
            is.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            //处理一
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            //处理二
        }

    }

提早抛出:有些比较明确的异常需要提前抛出,这样我们可以通过控制台打印的异常信息快速定位到出错的代码块,同时也可以避免不必要的对象构造或者资源调用。如下分别在调用两个方法的时候fileName参数都传递为null,显然采用代码二的方式更有利排查错误。
代码一:

@SuppressWarnings("resource")
    public void readFile(String fileName) throws IOException {
        InputStream is=new FileInputStream(fileName);
        is.read();
        is.close();
    }
    Exception in thread "main" java.lang.NullPointerException
    at java.io.FileInputStream.<init>(FileInputStream.java:130)
    at java.io.FileInputStream.<init>(FileInputStream.java:93)
    at com.javaweb.test.ExceptionTest.readFile(ExceptionTest.java:27)
    at com.javaweb.test.ExceptionTest.main(ExceptionTest.java:17)

代码二:

@SuppressWarnings("resource")
    public void readFile(String fileName) throws IOException {
        if(fileName==null){
            throw new IllegalArgumentException("fileName must not be null");
        }
        InputStream is=new FileInputStream(fileName);
        is.read();
        is.close();
    }
    Exception in thread "main" java.lang.IllegalArgumentException: fileName must not be null
    at com.javaweb.test.ExceptionTest.readFile(ExceptionTest.java:27)
    at com.javaweb.test.ExceptionTest.main(ExceptionTest.java:17)

延迟捕获:让异常捕获处理放在最外层进行处理,这样才能根据不同的情况进行不同的处理。如下面代码:

@SuppressWarnings("resource")
    public void readFile(String fileName) {
        if(fileName==null){
            throw new IllegalArgumentException("fileName must not be null");
        }
        InputStream is;
        try {
            is = new FileInputStream(fileName);
            is.read();
            is.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

在readFile这个方法中处理异常的方法并没有直接抛出而是捕获处理,看起来可能没有什么错误。但在上层引用中,不同的业务逻辑对待处理异常的方式可能不同,所以对于底层方法出现的异常需要进行抛出。

针对潜在的运行时异常是否应该对其做处理?

代码一:

@SuppressWarnings("resource")
    public void readFile(String fileName) throws IOException {
        if(fileName==null){
            throw new IllegalArgumentException("fileName must not be null");
        }
        InputStream is=new FileInputStream(fileName);
        is.read();
        is.close();
    }

代码二:

public int divide(int a ,int b){
        int result=0;
        if(b!=0){
            result=a/b;
        }
        return result;
    }

通过对比代码一与代码二,可以总结一些规律。针对存在潜在运行时异常的代码块,如果能通过逻辑处理从而避免抛出异常,那么就对代码进行逻辑处理;如果无法进行逻辑处理从而避免抛出异常,那么就及时抛出异常。

catch中通过throw继续抛出异常,此时throw抛出的异常如何被接收?

@Override
    public void add(Category bean) {
        // TODO Auto-generated method stub
        try {
            QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
            String sql="INSERT INTO category (id,name,description) VALUES(?,?,?)";
            Object[] params={bean.getId(),bean.getName(),bean.getDescription()};
            qr.update(sql, params);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            throw new RuntimeException(e);
        }
    }

如果上层方法直接或者间接调用这个add(),那么我们可以通过在上层方法中使用try-catch捕获这个异常

猜你喜欢

转载自blog.csdn.net/qq_31071543/article/details/80842417