Является ли перехват NumberFormatException плохой практикой?

Мне нужно проанализировать строку, которая может принимать шестнадцатеричные значения или другие не шестнадцатеричные значения

0xff, 0x31 или A, PC, label и так далее.

Я использую этот код, чтобы разделить два случая:

String input = readInput();

try {
    int hex = Integer.decode(input);            
    // use hex ...

} catch (NumberFormatException e) {
   // input is not a hex, continue parsing
}

Можно ли считать этот код «некрасивым» или трудным для чтения? Есть ли другие (может быть, более элегантные) решения?

РЕДАКТИРОВАТЬ: я хочу уточнить, что (в моем случае) неправильный ввод не существует: мне просто нужно различать, является ли это шестнадцатеричным числом или нет. И для полноты картины я делаю простой сборщик для DCPU-16.


person Community    schedule 22.06.2012    source источник
comment
Это не обязательно плохая практика, но она может помочь показать нам, как выглядит ввод. ИМО, вы можете никогда не проверять ошибки достаточно.   -  person Chris Dargis    schedule 22.06.2012
comment
Я считаю, что это некрасиво и трудно читать, но лучшего решения нет. Это одна из причин, по которой мне не нравятся проверенные исключения c2.com/cgi/wiki?TheProblemWithCheckedExceptions   -  person Juan Mendes    schedule 22.06.2012
comment
Вы можете найти этот вопрос уместным.   -  person Michael McGowan    schedule 22.06.2012
comment
Вы когда-нибудь решали эту проблему?   -  person Alex Lockwood    schedule 26.06.2012
comment
@AlexLockwood Я все еще надеялся на новые ответы ... безуспешно :) Поэтому я заключу исключение в логический метод isHex (String str), просто для ясности :)   -  person    schedule 28.06.2012
comment
@integeruser звучит хорошо. это звучит как то, о чем вам не нужно слишком сильно беспокоиться ... просто делайте это так, как вы считаете, что лучше всего :)   -  person Alex Lockwood    schedule 28.06.2012


Ответы (7)


Обработка исключений является неотъемлемой частью (и одной из целей разработки) языка программирования Java ... вы не должны отказываться от них только потому, что считаете их «уродливыми».

Тем не менее, если вам нужен простой и понятный способ обработки NumberFormatExceptions, вы можете вместо этого рассмотреть возможность использования класса NumberUtils.

Метод toInt(String str, int defaultValue) преобразует String в int, возвращая значение по умолчанию, если преобразование не удалось. Если строка null, возвращается значение по умолчанию.

 NumberUtils.toInt(null, 1) = 1
 NumberUtils.toInt("", 1)   = 1
 NumberUtils.toInt("1", 0)  = 1

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

public static int toInt(String str, int defaultValue) {         
    if(str == null) {
        return defaultValue;
    }
    try {
        return Integer.parseInt(str);
    } catch (NumberFormatException nfe) {
        return defaultValue;
    }
}
person Alex Lockwood    schedule 22.06.2012
comment
@integeruser, если неправильный ввод не существует, то, конечно, ваш код в порядке, как написано выше ... на самом деле, я не верю, что есть другой возможный способ избежать сбоя программы без обработки NumberFormatException. .. подскажите пожалуйста, в чем проблема? - person Alex Lockwood; 23.06.2012
comment
Мне нужно проверить, является ли строка шестнадцатеричным числом или нет. Да, мой код работает, но я считаю его уродливым и не думаю, что это лучший подход. См. Ответ pb2q. - person ; 23.06.2012
comment
@integeruser, я согласен с вами в том, что аспект обработки исключений может выглядеть некрасиво, но в большинстве ситуаций нет способа избежать этого. один из способов, которым вы можете сделать свой код немного красивее (как также описано в pp2q), - это заключить ваш код в какой-либо вспомогательный метод. таким образом вы разделяете функциональность своих методов ... методы, которые служат одной цели, не будут загромождены перехватом / обработкой исключений. Не уверен, что сейчас у меня есть смысл, но, надеюсь, я понял свою точку зрения, ха-ха - person Alex Lockwood; 23.06.2012
comment
Я согласен с вами :) и я думаю, что оберну исключение в метод. Я считаю неразумным то, что такие методы, как isInt или isHex, еще не включены в некоторые классы Java: P - person ; 23.06.2012
comment
Да, ну ... к счастью для вас, методы, представленные в классе NumberUtils, по большей части чрезвычайно просты. Я бы даже не стал импортировать эти классы в ваш проект ... Я бы просто скопировал и вставил нужные вам методы прямо в ваш код или в какой-то служебный класс и т. Д. Сообщите мне, чем вы закончите делать :) - person Alex Lockwood; 23.06.2012

Это ваш второй вопрос, который я сегодня видел по этому поводу.

Нет, это исключение вполне уместно.

И это определенно лучшая форма для перехвата более явного исключения (например, «NumberFormatException»), чем универсальное «Exception».

ПО МОЕМУ МНЕНИЮ...

PS: Где вы ставите исключение: на этом уровне или выше - это другой вопрос.

Эмпирическое правило - «самый низкий уровень, на котором вы знаете, что произошло, и как лучше всего восстановиться».

Или, иначе говоря (цитата из ссылки ниже):

«Метод должен перехватывать исключение только в том случае, если он может обработать его разумным способом».

Вот обсуждение:

person paulsm4    schedule 22.06.2012
comment
Я не согласен с тем, что «определенно» лучше улавливать более явные исключения. Если какой-то метод может генерировать ряд исключений, и вы не можете адекватно восстановить ни одно из них, тогда зачем беспокоиться о чем-либо, кроме как перехватить «Исключение» (или что-то еще) и зарегистрировать его. Я согласен со вторым процитированным пунктом, метод должен только улавливать исключение ... - person Tony Ennis; 22.06.2012
comment
Я не думаю, что ваш ответ действительно отвечает на вопрос, который не о как / когда мне использовать исключения, а об использовании исключений, когда это может быть более подходящим использовать, например, если еще. - person pb2q; 22.06.2012

Нет, это не «плохая практика». Это просто зависит от ситуации.

Например, в Android, если пользователь вводит строку «123a» в текстовое поле, которое должно принимать только целые числа, и впоследствии анализируется, будет выдано исключение, вызывающее сбой приложения. В этом случае имеет смысл перехватить исключение и предложить пользователю повторно ввести текст.

person Alex Lockwood    schedule 22.06.2012
comment
Кстати, для тех из вас, кто разрабатывает для Android, я знаю, что вы должны использовать вместо этого атрибут android:inputType ... не ненавидьте. - person Alex Lockwood; 22.06.2012

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

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

Кроме того, использование Exception делает менее читабельным код: без комментариев к данным он скрывает тот факт, что перемежающиеся не шестнадцатеричные цифры являются приемлемым и ожидаемым вводом.

Сказав это предпочтение, я мог бы использовать обработку исключений для обработки этого случая, и я определенно вижу много кода, который это делает. В этой комбинации decode / parseInt / NumberFormatException для вас заключено множество хороших функций. Я бы не стал использовать это без явного комментария, четко объясняющего, что я делаю.

person pb2q    schedule 22.06.2012
comment
Обработка исключений - это хорошо. Другой человек, который спрашивал сегодня ранее, прямо спросил, можно ли считать уродливым просто наличие блока try / catch. Нет! Нет ничего более далекого от правды. В этом конкретном случае я твердо верю, что обработчик исключений подходит и ... и идеален. По нескольким причинам. ПО МОЕМУ МНЕНИЮ... - person paulsm4; 22.06.2012
comment
PS: Я согласен с вашим утверждением об исключительных условиях. Некоторые думают, что исключения следует использовать только для ошибок. Нет: их можно с пользой использовать в любом сценарии, который не соответствует стандартному потоку. Хорошая точка зрения ;)! - person paulsm4; 23.06.2012

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

person Rocky Pulley    schedule 22.06.2012

Это Not about how good you code looks, но _2 _.......... Ya offcourse it should be readable, Как известно ...

Любой дурак может написать код, понятный компьютеру, но только великие программисты могут писать коды, понятные людям.

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

When you want to catch multiple exceptions which belong to the same inheritance tree, then create a try block, and multiple catch blocks from more specific to more abstract.

eg:

`Animal <--- Carnivores <--- Dog`

Теперь предположим, что есть DogException, CarnivoresException, AnimalException.

Тогда должно быть так,

try{

           // your code 

     }
      catch(DogException d){}
      catch(CarnivoresException c){}
      catch( AnimalException a){}

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

Если нет наследования, то ловить можно в любом порядке ...

person Kumar Vivek Mitra    schedule 22.06.2012
comment
Я полагаю, что ваше первое утверждение верно, однако почти весь код, используемый в профессиональной среде, будет содержать ошибки либо изначально, либо по мере добавления. Таким образом, имеет значение то, насколько хорошо выглядит ваш код, или, скорее, насколько читабельно ваш код имеет значение. - person BlackVegetable; 22.06.2012

Это лучшее, что ты можешь сделать. Метод либо вернет какой-то индикатор успеха / ошибки, либо вызовет исключение, это просто вопрос, что наиболее удобно. Здесь Sun приняла решение за нас, поэтому нет необходимости в дебатах.

Что меня больше всего беспокоит, так это то, что исключение будет включать полную трассировку стека! В вашем конкретном случае, если вы читаете миллионы этих строк, вы заметите (совершенно ненужную) низкую производительность. Если это важно для вас, вы можете подумать о написании собственного метода (вы можете использовать код Sun в качестве руководства). Затем вы можете решить для себя, хотите ли вы использовать исключение или нет. Если вы это сделаете, держите под рукой статическую копию исключения и всегда бросайте ее, чтобы сэкономить время. И переопределите fillInStackTrace, чтобы он ничего не делал, и у вас не было бессмысленной трассировки стека в вашем исключении.

person RalphChapin    schedule 22.06.2012