正确使用IllegalArgumentException

时间:2014-05-22 14:26:43

标签: java exception exception-handling illegalargumentexception

原始问题是here

我正在读取UTF-8文件并解析该文件的内容。如果文件中有错误,则无法继续执行,应停止执行。如果内容有问题,我建议抛出IllegalArgumentException,但API文档说:

  

抛出表示某个方法已被传递为非法或   不恰当的论点。

在我的代码中,参数将是我传递的文件(或实际上是路径),如果在解析时出现问题,抛出IllegalArgumentException是否正确?如果没有,我应该抛出什么类型的异常?

private char[][] readMazeFromFile(Path mazeFile) throws IOException {
    if (!Files.isRegularFile(mazeFile) || !Files.isReadable(mazeFile)) {
        throw new IllegalArgumentException("Cannot locate readable file " + mazeFile);
    }
    List<String> stringList = Files.readAllLines(mazeFile, StandardCharsets.UTF_8);
    char[][] charMaze = new char[stringList.size()][];

    for (int i = 0; i < stringList.size(); i++) {
        String line = stringList.get(i);
        if (line.length() != charMaze.length)
            throw new IllegalArgumentException(String.format("Expect the maze to be square, but line %d is not %d characters long", line.length(), charMaze.length));
        if (line.contains("B")) {
            startX = i;
            startY = line.indexOf("B");
        }
        if (line.contains("F")) {
            endX = i;
            endY = line.indexOf("F");
        }
        charMaze[i] = line.toCharArray();
    }

    if (startX == -1 || startY == -1)
        throw new IllegalArgumentException("Could not find starting point (B), aborting.");
    if (endX == -1 || endY == -1)
        throw new IllegalArgumentException("Could not find ending point (F), aborting.");
    return charMaze;
}

3 个答案:

答案 0 :(得分:5)

我认为第一种用法是正确的:

if (!Files.isRegularFile(mazeFile) || !Files.isReadable(mazeFile)) {
    throw new IllegalArgumentException("Cannot locate readable file "+mazeFile);
}

由于(如文档所述)提供了无效文件作为参数,因此应该抛出IllegalArgumentException。 一旦你知道你有一个满足这些要求的实际文件,我个人不认为这是一个很好的例外。这将导致其他开发人员质疑给定的参数类型而不是文件的内容。我想你的选择是:

  • 保持原样,只需使用非常特定的错误消息进行解释 为什么这是一个无效的论点。

  • 使用其他一些可能更适用的java异常,例如java.text.ParseException,因为它是导致错误的文件解析。

  • 创建一个自定义异常类,可以更充分地描述文件的问题,例如: MazeParseException(根据评论)或FileFormatException

如果您预计其他几位开发人员会执行您的功能,我希望第二个或第三个选项更有用。

答案 1 :(得分:1)

例外主要不是名字,我最好的建议就是制作自己的名字。 主要原因是IllegalArgumentException未经检查的例外,因为它们会扩展java.lang.RuntimeException。如果你在这样的上下文中使用它们,它们只会引起问题。 (Source)

将方法签名更改为

private char[][] readMazeFromFile(Path mazeFile) throws IOException, MazeParseException {...}

所有throw new IllegalArgumentExceptionthrow new MazeParseException (根据@ Joel的回答第一次使用除外)

MazeParseException.java文件:

package yourPackage.here;

import java.lang.Exception;

public class MazeParseException {
    public MazeParseException() {
        super();
    }

    public MazeParseException(String reason) {
        super(reason);
    }
}

使用您自己的例外的好处是您可以标记额外数据以及与您的情况相关的例外,例如您可以添加:

private int errorLineNum = null;
public MazeParseException(String reason, int lineNum) {
    this(reason);
    this.errorLineNum = lineNum;
}

public int getMalformedLine() {
    return this.errorLineNum;
}

// And then update the toString() method to incorperate the errorLineNum
@Override
public String toString() {
    StringBuilder sb = new StringBuilder(super.toString());
    if(errorLineNum != null) {
        sb.append("@ line #");
        sb.append(this.errorLineNum);
    }
    return sb.toString();

}

答案 2 :(得分:0)

如果文件与他们正在寻找的文件(JSON文件或XML文件)不匹配,JSON或XML库会发送自己的execption,我认为如果不匹配则应该这样做你在找什么(UTF-8文件)。

IllegalArgumentException应该用于代码中的内部问题,并且在代码调试时不应该抛出。此外,您不应该捕获IllegalArgumentException,并且您可能希望在程序中捕获它。