有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java准确定位异常错误的最佳方法是什么?

我读过很多关于异常的书,但我很难把它们拼凑在一起。。。我正在尝试编写一个用于读取文件的实用方法(这是为了练习,所以我对使用库不感兴趣):

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) 个答案

  1. # 1 楼答案

    异常可以是对象层次结构的一部分,它允许您详细处理异常,或者在您觉得方便的任何抽象级别上处理异常。例如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 
    } 
    
  2. # 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);
    }
    

    如果错误处理只需要打印错误消息,那么这是一个不错的选择