Как правильно обрабатывать исключение NumberFormatException, когда оно ожидается? - PullRequest
17 голосов
/ 10 декабря 2010

Я сталкиваюсь с такой ситуацией, когда мне нужно разобрать 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 не воспринимал это как «незарегистрированный».

Ответы [ 8 ]

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

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

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

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

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

Может быть способ заставить CodePro игнорировать это конкретное предупреждение.Конечно, с помощью таких инструментов, как FindBugs и Checkstyle, вы можете отключить предупреждения в определенных местах.(РЕДАКТИРОВАТЬ: @Andy указала, как это сделать.)

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

int parseWithDefault(String s, int def) {
    try {
        return Integer.parseInt(s);
    }
    catch (NumberFormatException e) {
        // It's OK to ignore "e" here because returning a default value is the documented behaviour on invalid input.
        return def;
    }
}
9 голосов
/ 10 декабря 2010

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

NumberUtils.toInt("123", 42) ==> 123
NumberUtils.toInt("abc", 42) ==> 42
3 голосов
/ 10 декабря 2010
* 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

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

1 голос
/ 10 декабря 2010

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

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. «плохая форма» , о которой вы говорите, о плохой практике слепого и бездумного написания пустых блоков улова и никогда не возвращаются к истинному рассмотрению и рассмотрению дела.Если рассматривается исключительная ситуация и она правильно делает для ситуации (, даже если правильно ничего не делать ), то вы "обработали" исключение.

0 голосов
/ 13 декабря 2012

Как уже упоминалось, нет встроенного базового метода 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 в вашем коде и нажать Открыть объявление.

0 голосов
/ 10 декабря 2010

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

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

0 голосов
/ 10 декабря 2010

Ваш первый кодовый блок правильный.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's needed
        return 0;
    }
    return i;
}
0 голосов
/ 10 декабря 2010

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...