Подтвердить что ты не робот

Каков правильный способ обработки исключения NumberFormatException, когда он ожидается?

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

private int getCurrentPieceAsInt() {
    int i = 0;
    try {
        i = Integer.parseInt(this.getCurrentPiece());
    } catch (NumberFormatException e) {
        i = 0;
    }
    return i;
}

Я хочу просто упростить свой код, как это. У компилятора нет проблем с ним, но поток умирает на NumberFormatException.

private int getCurrentPieceAsInt() {
    int i = 0;
    i = Integer.parseInt(this.getCurrentPiece());
    return i;
}

Google CodePro хочет, чтобы я каким-то образом зарегистрировал исключение, и я согласен, что это лучшая практика.

private int getCurrentPieceAsInt() {
    int i = 0;
    try {
        i = Integer.parseInt(this.getCurrentPiece());
    } catch (NumberFormatException e) {
        i = 0;
        e.printStackTrace();
    }
    return i;
}

Я хочу, чтобы этот метод возвращал 0, когда текущая часть не является числом или не может быть проанализирована. Когда я не поймаю NumberFormatException явно, не присваивает ли переменной i? Или есть какое-то значение по умолчанию, которое возвращает Integer.parseInt()?

В общем стиле говорится, что если я поймаю исключение, я должен его зарегистрировать где-нибудь. Я не хочу регистрировать его. Это обычная операция для того, чтобы это исключение иногда возникало, что также не очень хорошо сочетается со мной. Однако я не могу найти функцию, которая скажет мне, будет ли Integer.parseInt() выдавать исключение. Поэтому мой единственный курс действий - просто вызвать его и поймать исключение.

javadoc для parseInt не очень помогает.

Вот конкретные вопросы, которые я хотел бы знать:

  • Есть ли способ, который я могу назвать, который скажет мне, если Integer.parseInt() будет бросать NumberFormatException, прежде чем называть его? Тогда у меня не было бы проблем записывать это, так как это никогда не должно происходить.
  • Если я просто не поймаю исключение, будет ли нецелесообразным назначаться? Затем я просто инициализирую его до значения, которое я хочу, когда оно не является числом, и не поймает исключение.
  • Есть ли способ отметить исключение как-то явно, что меня это не волнует? Я думаю, что это будет похоже на AWTEvent.consume(). Если это так, то я сделаю это, чтобы Google CodePro не считал это "незамкнутым".
4b9b3361

Ответ 1

  • Есть ли метод, который я могу вызвать, который скажет мне, будет ли Integer.parseInt() вызывать исключение NumberFormatException перед его вызовом? Тогда у меня не было бы проблем записывать это, так как это никогда не должно происходить.

К сожалению, нет. По крайней мере, не в базовом Java API. Легко написать, однако, просто измените код ниже.

  • Если я просто не поймаю исключение, будет ли нецелесообразным назначаться? Затем я просто инициализирую его до значения, которое я хочу, когда оно не является числом, и не поймает исключение.

Если вы не поймаете исключение, тогда стек будет разворачиваться до тех пор, пока он не ударит по блоку catch, который будет обрабатывать его, или он полностью отключится и остановит поток. Переменная, по сути, не будет назначена, но это не совсем то, что вы хотите.

  • Есть ли способ отметить исключение как-то явно, что меня это не волнует? Я думаю, что это будет нечто похожее на AWTEvent.consume(). Если это так, то я сделаю это, чтобы Google CodePro не считал это "незамкнутым".

Возможно, есть способ сообщить CodePro игнорировать это конкретное предупреждение. Конечно, с помощью инструментов, таких как FindBugs и Checkstyle, вы можете отключать предупреждения в определенных местах. (EDIT: @Энди указал, как это сделать.)

Я подозреваю, что вы хотите, это что-то вроде пакета Commons lang, упомянутого @daveb. Очень легко написать такую ​​функцию:

int parseWithDefault(String s, int def) {
    try {
        return Integer.parseInt(s);
    }
    catch (NumberFormatException e) {
        // It OK to ignore "e" here because returning a default value is the documented behaviour on invalid input.
        return def;
    }
}

Ответ 2

Существует NumberUtils.toInt(String, int) в commons lang, который будет делать именно то, что вы хотите.

NumberUtils.toInt("123", 42) ==> 123
NumberUtils.toInt("abc", 42) ==> 42

Ответ 3

* Is there a way to mark the exception somehow explicitly that I don't care about it? I'm thinking this would be something similar to AWTEvent.consume(). If so, then I will do this so that Google CodePro doesn't see this as "unlogged".

Да, вы можете локально отключить правило аудита CodePro для одной строки кода:

http://code.google.com/javadevtools/codepro/doc/features/audit/locally_disabling_audit_rules.html

Тем не менее, необязательно включать диагностическое ведение журнала в каждом блокировании catch. Иногда лучше всего принять курс по умолчанию. Иногда он взаимодействует с пользователем. Это зависит.

Ответ 4

Создайте свой собственный метод удобства для использования в настоящее время и в будущем:

public static int parseInt(final /*@Nullable*/ String s, final int valueIfInvalid) {
    try {
        if (s == null) {
            return valueIfInvalid;
        } else {
            return Integer.parseInt(s);
        }
    } catch (final NumberFormatException ex) {
        return valueIfInvalid;
    }
}

Есть ли метод, который я могу вызвать, который скажет мне, будет ли Integer.parseInt() вызывать исключение NumberFormatException перед его вызовом? Тогда у меня не было бы проблем записывать это, так как это никогда не должно происходить.

Не то, чтобы я знал. Имейте в виду, что если бы это было так, вы, вероятно, в конечном итоге разобрали значение дважды (один раз для проверки и один раз для его анализа). Я понимаю, что вы хотите избежать исключения, но в этом случае это исключение - это стандартная идиома в Java, и она не предоставляет другого (по крайней мере, того, что я знаю).

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

Вы должны поймать исключение (даже если оно ничего не делает), или оно выйдет из блока и выкинет через стек.

Есть ли способ отметить исключение как-то явно, что меня это не волнует? Я думаю, что это будет нечто похожее на AWTEvent.consume(). Если это так, то я сделаю это, чтобы Google CodePro не считал это "незамкнутым".

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

Я бы не зарегистрировал его, если это действительно нормальное состояние, которое вы обрабатываете. Я не знакомый с Google CodePro, но я надеюсь, что есть способ подавить предупреждение, например. некоторая аннотация/ключевое слово @SuppressWarnings ( "xxx" ).


Изменить: я хотел бы отметить эти комментарии в комментариях ниже

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

.

... Исключение (ситуация) обрабатывается возвратом указанного значенияIfInvalid. "плохая форма" вы ссылаетесь на неудовлетворительную практику слепого и бездумного написания пустых блоков catch и никогда не вернетесь к истинному рассмотрению и рассмотрению дела. Если ситуация с исключением рассматривается и делает правильную вещь для ситуации (даже если правильная вещь ничего не делает), тогда вы обработали исключение.

Ответ 5

Вы должны поймать Исключение, как вы это делаете. Это раздражает, но лучший подход.

Нет метода Java API, который вернет 0, если строка не является допустимым int.

Когда строка не является int, будет выбрано исключение, поэтому ваша переменная int не будет установлена, если вы не поймаете исключение, как вы это делаете.

Ответ 6

Ваш первый блок кода правильный. i не будет неявно преобразован в 0, когда возникает исключение, и вы должны поймать это исключение. Установка i в 0 внутри catch верна; хотя вы можете просто заменить i = 0; на return 0;. В этом случае вы не можете избежать обработки исключений.

Чтобы уточнить, вы можете использовать это:

private int getCurrentPieceAsInt() {
    int i = 0;
    try {
        i = Integer.parseInt(this.getCurrentPiece());
    } catch (NumberFormatException e) {
        // log that an exception occured if it needed
        return 0;
    }
    return i;
}

Ответ 7

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

Регистрация исключения более полезна, если вы не знаете, как обрабатывать исключение, и оставляете его человеку, читающему журналы.

Ответ 8

Как уже упоминалось, не существует встроенного метода Java API, который вы можете вызвать для проверки целого числа, но вы можете использовать класс Character для проверки ввода без, используя исключение обработки. Например:

package com.example.parseint;

public class ValidateIntExample {
    public static boolean isInteger(String s) {
        if (s == null) {
            return false;
        }

        s = s.trim();

        if (s.length() == 0) {
            return false;
        }

        int start = 0;
        if (s.charAt(0) == '-') { // handle negative numbers
            if (s.length() == 1) {
                return false;
            }
            else {
                start = 1;
            }
        }

        for (int i = start; i < s.length(); i++) {
            if (! Character.isDigit(s.charAt(i))) {
                return false;
            }
        }

        return true;
    }
}

Фактически, parseInt сам использует Character.isDigit внутренне, что вы можете проверить в исходном коде JRE. (Извините, я бы включил здесь метод parseInt, но я не уверен, разрешено ли мне по условиям лицензии.) Если вы используете Eclipse, и у вас есть исходный код JRE, прикрепленный к вашему проекту, вы можно щелкнуть правой кнопкой мыши по методу Integer.parseInt в вашем коде и нажать "Открыть декларацию".