2017-02-21 44 views
1

Действительно, я не совсем понимаю, что считается ошибкой на Java.Ошибка Java против незаконного аргумента

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

Что я не понимаю, почему первый случай - это логическая ошибка, но в другом случае «внешний пользователь не предоставил правильные аргументы»?

Скажем, у меня есть две функции:

public boolean isDigit(char c) { return c >= '0' && c <= '9'; } 
public int toInt(char c) { return c - '0'; } 

Во всех коде я пишу, перед вызовом toInt, я бы проверить, чтобы убедиться, что это цифра первого, или иначе это не имеет смысла!

Но из того, что я прочитал, пользователю разрешено делать вещи, которые не имеют смысла; код должен проверять это?

Чтобы сделать код надежным, я бы добавил утверждение, чтобы убедиться, что параметры правильные. Это только для проверки ошибок во время отладки ....

public int toInt(char c) { assert isDigit(c); return c - '0'; } 

Но я читал, что это не так, как вы должны сделать это в Java? Вы должны сделать:

public int toInt(char c) { 
    if (!isDigit(c)) { 
     throw new IllegalArgumentException("char is not a digit"); 
    } 
    return c - '0'; 
} 

Это действительно некрасиво для меня видеть, потому что я уже должен проверить, что пары действуют перед вызовом функции! Оптимизирована ли двойная проверка?

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

char c = '0'; 
if (isDigit(c)) { 
    int i = toInt(c); 
} else { 
    doSomethingElse...; 
} 

становится так:

char c = '0'; 
if (isDigit(c)) { 
    if(!isDigit(c)) { 
     throw new IllegalArgumentException("char is not a digit"); 
    } 
    int i = c - '0'; 
} 
... 

Так это нормально, что все излишне дважды проверяется? Это Java-способ делать вещи?

Если это так, я хочу знать, как могло возникнуть исключение IllegalArgumentException, кроме ошибки в логике, потому что я действительно этого не понимаю. Это действительно меня задевает, потому что для меня нет смысла, что кто-то фактически поставил бы аргумент, не проверив сначала, что он действителен. Благодаря!

Вкратце вопрос может быть: Нормально, что все проверено на согласованность несколько раз, даже если они известны как правильные, и как происходит, что незаконный аргумент передается после того, как он был проверен, чтобы убедиться это верно?

+0

Ошибки, вызывающие частные функции, являются вашими и вам нужна фиксация, прежде чем вы отправляете. Ошибки, вызывающие публичные функции, являются чьими-то и требуют их исправления до их отправки, но 'assert' считается слишком резким для этого использования. – EJP

+0

Итак, в целом, это обычный «личный выбор», который делает так, что это делается на Java? Это как если бы они могли поставить два типа утверждений, частные утверждают для вашего кода и публичные для других людей, использующих его! –

+0

Вы неверно представили 'assert'. Цель 'assert' - документировать инварианты в коде. Он не проверяет достоверность, он утверждает, что ваш код уже должен быть проверен. Затем ваш избыточный код является результатом вашего письма. Это не должно быть так. Вы кодируете то, что вам нужно, чтобы получить нужный результат. Если вам нужно что-то не «null», очень хороший способ сделать его «final» и отклонить «null» в конструкторе. Затем вы можете «утверждать атрибут! = Null;' _instead of_ проверять его в другом месте класса. –

ответ

0

«Для меня нет смысла, что кто-то фактически поставил бы аргумент, не проверив его, прежде чем он будет проверен». И все же это происходит все время. Вот как происходят ошибки. Лучшие практики существуют, потому что они работают в реальном мире, и API пишет блокирующие инварианты (вещи, которые просто должны быть такими), потому что это единственный способ быть уверенным, что вещи не сломаются. Поэтому «для меня» бесполезно с технической точки зрения, только «что есть».

Чтобы ответить на ваш вопрос, «все излишне дважды проверено?», Нет. Только когда кто-то делает это неправильно. Чтобы сделать это правильно, вы делаете то, что необходимо только, и вы предотвращаете необходимость двойной проверки.

Точка исключения во время выполнения, например IllegalArgumentException, сигнализирует программисту (кто «вам» не должен был проходить незаконный аргумент), который они испортили. В этом-то и дело.

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

Потому что сбои в программе вредны.

«Я читал, что вы должны использовать утверждение, чтобы проверить свой код только в частных функциях». Прекратите читать этих авторов. Вы не используете assert, чтобы проверить свой код. Вы используете программную логику, чтобы проверить свои входы и условия. (То, что вы назвали if.) Вы используете assert для подтверждения инвариантов. Например, если вы берете char, который должен быть цифрой, вы, конечно, проверяете, что это цифра! Если вы не выполнили свою программу, или, что еще хуже, не потерпите крах, но дадите плохие результаты.

Что бы вы еще сделали?

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

if (! isDigit(c)) { throw new IllegalArgumentException("non-digit");} 
assert isDigit(c); 

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

 Смежные вопросы

  • Нет связанных вопросов^_^