Правильное использование IllegalArgumentException

оригинальный вопрос здесь

Я читаю в файле 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 ответов


Я думаю, что первое использование правильно:

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

поскольку (как указано в документации) в качестве аргумента был предоставлен недопустимый файл, это должно вызвать IllegalArgumentException. Как только вы узнаете, что у вас есть фактический файл, который соответствует этим требованиям, я лично не думаю, что это хорошее исключение. Это заставит других разработчиков усомниться в типе аргумента, который был задан в отличие от содержимого файла. Думаю, у тебя есть варианты. являются:

  • держите его как есть, только с очень конкретные сообщения об ошибке, объясняющее почему это был неверный аргумент.

  • используйте другое, потенциально более применимое исключение java, такое как java.text.ParseException, так как это разбор файла, который вызывает ошибку.

  • создайте пользовательский класс исключений, который более подробно описывает проблему с файлом, например a MazeParseException (согласно комментарии) или FileFormatException.

Я ожидаю, что второй или третий вариант будет более выгодным, если вы ожидаете, что несколько других разработчиков выполнят вашу функцию.


исключения в основном не что иное, как имена, мой лучший совет здесь было бы сделать свой собственный. Основная причина в том, что IllegalArgumentExceptionС неотмеченные исключения потому что они расширяют java.lang.RuntimeException. Они просто вызовут проблемы, если вы используете их в таком контексте. (источник)

измените сигнатуру метода на

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

и throw new IllegalArgumentException С throw 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();

}

поскольку JSON или XML-библиотека отправляют свое собственное исполнение, если файл не соответствует тому, что они ищут (файл JSON или XML), я думаю, вы должны сделать то же самое, если не соответствует тому, что вы ищете( файл UTF-8 ).

IllegalArgumentException должен использоваться для внутренней проблемы в коде и не должен быть брошен, когда ваш код был отлажен. Также вы не должны поймать IllegalArgumentException, и вы, вероятно, захотите поймать его в своей программе.