准确查明异常错误的最佳方法是什么?

时间:2016-05-08 20:16:50

标签: java exception exception-handling

我已经阅读了很多关于异常的内容,但是我很难将它们拼凑在一起......我正在尝试编写一个实用的方法来读取文件(这是为了练习所以我不感兴趣在使用图书馆):

public static List<String> readFile(String file)
        throws NoSuchFileException,
               AccessDeniedException,
               SomeException1,
               SomeException2,
               IOException {
    Path p = Paths.get(file);
    if (!Files.exists(p)) {
        throw new NoSuchFileException(file);
    } else if (!Files.isRegularFile(p)) {
        throw new SomeException1(file);
    } else if (!Files.isReadable(p)) {
        throw new AccessDeniedException(file);
    } else if (Files.size(p) == 0) {
        throw new SomeException2(file);
    }
    return Files.readAllLines(p);
}


public static void main(String[] args) {
    try {
        if (args.length != 2) {
            System.out.println("The proper use is: java MyProgram file1.txt file2.txt");
            return;
        }

        List<List<String>> files = new ArrayList<>();
        for (int i = 0; i < args.length; i++) {
            try {
                files.add(Utilities.readFile(args[i]));
            } catch (NoSuchFileException e) {
                System.out.printf("File %s does not exist%n", e.getMessage());
                System.exit(-1);
            } catch (SomeException1 e) {
                System.out.printf("File %s is not a regular file%n", e.getMessage());
                throw e;
            } catch (AccessDeniedException e) {
                System.out.printf(
                    "Access rights are insufficient to read file %s%n", e.getMessage()
                );
                throw new AccessDeniedException(e);
            } catch (SomeException2 e) {
                System.out.printf("File %s is empty%n", e.getMessage());
                throw new SomeOtherException(e);
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

我想抛出精确的异常,以便我可以在以后捕获它们并为用户编写相关的错误消息,但这看起来很糟糕......有更好的方法吗?

我看到有几个问题,这是我的想法:

  1. 我很确定这是一个例外情况,而不是流控制,所以我应该使用例外。
  2. 我不能抛出一个常规异常,否则我将无法查明错误原因。
  3. 另一方面,这感觉太多例外,污染了方法签名。另外,我不能使用未经检查的异常,因为这些不是程序员错误,可以处理它们。
  4. 我找不到足够精确的标准例外用于我的用例。
  5. 但我不确定这是否是创建自定义类型的例外的正确时间,或者这是解决问题的错误方法......

2 个答案:

答案 0 :(得分:2)

如果您的异常都来自公共基本异常,例如IOException,则为基本异常添加throws声明就足够了:

public static List<String> readFile(String file)
        throws IOException {
    // ...
}

如果您不想为所有情况创建不同的例外,请使用附加到每个例外的消息:

public static List<String> readFile(String file)
        throws IOException {
    Path p = Paths.get(file);
    if (!Files.exists(p)) {
        throw new IOException( "No such file: " + file);
    } else if (!Files.isRegularFile(p)) {
        throw new IOException( "No regular file: " + file);
    } else if (!Files.isReadable(p)) {
        throw new IOException( "Access denied: " + file);
    } else if (Files.size(p) == 0) {
        throw new IOException( "Empty file: " + file);
    }
    return Files.readAllLines(p);
}

如果您需要为错误处理做的只是打印错误消息,这是一个不错的选择。

答案 1 :(得分:0)

异常可以是对象层次结构的一部分,它允许您详细处理异常或处理您认为方便的任何抽象级别。例如,FileNotFoundExceptionCharacterEncodingException都会延伸IOException。您可以选择在抽象IOException级别捕获它们,或者像这样单独处理它们:

catch(FileNotFouncException e){
    // handle it specifically
} 
catch(CharacterEncodingException e){
    // handle it specifically
}
catch(IOException e){
    // all others handle the same way
    // (Superclass must be handled after subclasses)
}

您还可以将没有方便的公共基类的异常分组,仅仅因为您想以相同的方式处理它们,如下所示:

catch(ZipException|ZipError e){
    // deal with corrupt zip file once, even though they come from different class hierarchies 
}