try catch 循环问题的真相

try catch在编码过程中经常使用,为了捕获可预见的异常,保证程序继续运行。

如果遇到循环处理逻辑,try catch应该放在循环内、还是循环外呢?

我这里记录一下:

通常的一种说法:

try catch放在循环内,异常自己捕获处理。其他循环可以继续执行。

放在循环外,循环体就视为一个整体,一旦发生异常,就不执行。

// 放在外部
try {
    for(int i=1;i<4;i++){
        int num = 1/0;
        System.out.println("i="+i);
    }
    System.out.println("try");
}catch (ArithmeticException ex){
    System.err.println("java.lang.ArithmeticException: / by zero");
}
System.out.println("go");

执行结果:直接报错,跳出try块。继续运行下面的代码。

// 放在内部
for(int i=1;i<4;i++){
    try {
        int num = 1/0;
        System.out.println("try");
    }catch (ArithmeticException ex){
        System.err.println("java.lang.ArithmeticException: / by zero");
    }
    System.out.println("i="+i);
}
System.out.println("go");

执行结果:

由于异常被捕获,会抛出异常。跳出try块。循环体内代码继续执行。

好戏才刚开始~

// 放在内部
for(int i=1;i<4;i++){
    try {
        File file = new File("D://test"+i);
        FileUtils.cleanDirectory(file);
        System.out.println("try");
    } catch (IOException e) {
        System.err.println("IOException"+i);
    }
    System.out.println("i="+i);
}

我的D盘,创建了一个test1、test3文件夹。

按照刚才的逻辑,虽然没有test2文件夹,会导致报错。但循环会继续执行。

执行结果:

Why?? 说好的循环内部try catch继续执行呢!

观察错误,发现异常其实未被程序捕获,我们被表象迷惑了!!

让我们看看源码:

/**
     * Cleans a directory without deleting it.
     *
     * @param directory directory to clean
     * @throws IOException              in case cleaning is unsuccessful
     * @throws IllegalArgumentException if {@code directory} does not exist or is not a directory
     */
    public static void cleanDirectory(final File directory) throws IOException {
        final File[] files = verifiedListFiles(directory);

        IOException exception = null;
        for (final File file : files) {
            try {
                forceDelete(file);
            } catch (final IOException ioe) {
                exception = ioe;
            }
        }

        if (null != exception) {
            throw exception;
        }
    }

虽然这个清空目录文件的方法,抛出的是IOException异常,我们catch也处理了。

但是它还主动抛出了其他的异常!!比如这里的运行时异常:IllegalArgumentException

/**
     * Lists files in a directory, asserting that the supplied directory satisfies exists and is a directory
     * @param directory The directory to list
     * @return The files in the directory, never null.
     * @throws IOException if an I/O error occurs
     */
    private static File[] verifiedListFiles(File directory) throws IOException {
        if (!directory.exists()) {
            final String message = directory + " does not exist";
            throw new IllegalArgumentException(message);
        }

        if (!directory.isDirectory()) {
            final String message = directory + " is not a directory";
            throw new IllegalArgumentException(message);
        }

        final File[] files = directory.listFiles();
        if (files == null) {  // null if security restricted
            throw new IOException("Failed to list contents of " + directory);
        }
        return files;
    }

于是我们将代码改为:

    // 放在内部
    for(int i=1;i<4;i++){
        try {
            File file = new File("D://test"+i);
            FileUtils.cleanDirectory(file);
            System.out.println("try");
        } catch (IOException e) {
            System.err.println("IOException"+i);
        } catch (IllegalArgumentException e){
            System.err.println("IllegalArgumentException"+i);
        }
        System.out.println("i="+i);
    }

执行结果: 虽然报错,但循环继续执行了。

提示:(更加粗暴的方式,就是直接抛出Exception错误,妥妥的都能捕获。运行时异常也是继承Exception的。)

END O(∩_∩)O

猜你喜欢

转载自blog.csdn.net/Cky079/article/details/83375038