Меня беспокоит, что это исключение во время выполнения, поэтому его, вероятно, следует использовать с осторожностью.
Стандартный вариант использования:
void setPercentage(int pct) {
if( pct < 0 || pct > 100) {
throw new IllegalArgumentException("bad percent");
}
}
Но похоже, что это приведет к следующему дизайну:
public void computeScore() throws MyPackageException {
try {
setPercentage(userInputPercent);
}
catch(IllegalArgumentException exc){
throw new MyPackageException(exc);
}
}
Чтобы вернуть его к проверенному исключению.
Хорошо, но давайте с этим. Если вы дадите неверный ввод, вы получите ошибку времени выполнения. Итак, во-первых, это на самом деле довольно сложно реализовать единообразно, потому что вам может потребоваться выполнить прямо противоположное преобразование:
public void scanEmail(String emailStr, InputStream mime) {
try {
EmailAddress parsedAddress = EmailUtil.parse(emailStr);
}
catch(ParseException exc){
throw new IllegalArgumentException("bad email", exc);
}
}
И что еще хуже - хотя 0 <= pct && pct <= 100
можно ожидать, что проверка клиентского кода будет выполняться статически, это не так для более сложных данных, таких как адрес электронной почты или, что еще хуже, что-то, что необходимо проверить в базе данных, поэтому в целом клиентский код не может предварительно проверить.
В общем, я хочу сказать, что я не вижу значимой последовательной политики использования IllegalArgumentException
. Похоже, его не следует использовать, и мы должны придерживаться наших собственных проверенных исключений. Какой хороший вариант использования для этого?
Говоря о «плохом вводе», вы должны учитывать, откуда он поступает.
Если ввод введен пользователем или другой внешней системой, которую вы не контролируете, вы должны ожидать, что ввод недействителен, и всегда проверять его. В этом случае совершенно нормально генерировать проверенное исключение. Ваше приложение должно «восстановиться» после этого исключения, предоставив пользователю сообщение об ошибке.
Если входные данные поступают из вашей собственной системы, например, из вашей базы данных, или из некоторых других частей вашего приложения, вы должны иметь возможность полагаться на то, что они действительны (они должны были быть проверены до того, как они попали туда). В этом случае совершенно нормально генерировать непроверенное исключение, такое как IllegalArgumentException, которое не должно быть перехвачено (в общем, вы никогда не должны перехватывать непроверенные исключения). Это ошибка программиста, что в первую очередь попало недопустимое значение;) Это нужно исправить.
источник
Because an unchecked exception is meant to be thrown as a result of a programming error
помогло прояснить много вещей в голове, спасибо :)Выбрасывание исключений времени выполнения «умеренно» на самом деле не является хорошей политикой - Effective Java рекомендует использовать проверенные исключения, когда можно разумно ожидать восстановления вызывающего . (Ошибка программиста - это конкретный пример: если конкретный случай указывает на ошибку программиста, тогда вы должны выбросить непроверенное исключение; вы хотите, чтобы программист имел трассировку стека того, где возникла логическая проблема, а не пытался решить ее самостоятельно.)
Если надежды на выздоровление нет, то смело используйте непроверенные исключения; нет смысла ловить их, так что это прекрасно.
Однако из вашего примера не на 100% ясно, в каком случае этот пример находится в вашем коде.
источник
foo(data)
могла произойти как часть,for(Data data : list) foo(data);
в которой вызывающий может пожелать, чтобы как можно больше успешно завершилось, даже если некоторые данные искажены. Включает также программные ошибки: если сбой моего приложения означает, что транзакция не будет выполнена, это, вероятно, лучше, если это означает, что ядерное охлаждение отключается, это плохо.StackOverflowError
и это случаи, от которых нельзя ожидать восстановления от вызывающего. Но похоже, что следует проверять любой случай уровня логики данных или приложения. Это означает, что проверяйте нулевой указатель!Как указано в официальном руководстве oracle, в нем говорится, что:
Если у меня есть приложение, взаимодействующее с базой данных с помощью
JDBC
, и у меня есть метод, который принимает аргумент какint item
иdouble price
.price
Для соответствующего элемента считываются из таблицы базы данных. Я просто умножаю общее количествоitem
купленных наprice
стоимость и возвращаю результат. Хотя я всегда уверен, что со своей стороны (со стороны приложения), значение поля цены в таблице никогда не может быть отрицательным. Но что, если значение цены окажется отрицательным ? Это показывает, что есть серьезная проблема со стороной базы данных. Возможно неправильный ввод цены оператором. Это проблема, которую другая часть приложения, вызывающего этот метод, не может предвидеть и не может исправить. В этом случае следует бросить, в котором будет указано, чтоBUG
в вашей базе данных. Итак, иIllegalArguementException()
the price can't be negative
.Надеюсь, что ясно выразил свою точку зрения.
источник
Любой API должен проверять правильность каждого параметра любого публичного метода перед его выполнением:
Они представляют собой 99,9% ошибок в приложении, потому что оно запрашивает невозможные операции, поэтому, в конце концов, они являются ошибками, которые должны привести к сбою приложения (так что это неисправимая ошибка).
В этом случае, следуя принципу быстрого сбоя, вы должны дать приложению завершить работу, чтобы не повредить его состояние.
источник
Рассматривайте
IllegalArgumentException
как проверку предварительных условий и учитывайте принцип проектирования: общедоступный метод должен как знать, так и публично документировать свои собственные предварительные условия.Я согласен, что этот пример верен:
Если EmailUtil непрозрачен , то есть по какой-то причине предварительные условия не могут быть описаны конечному пользователю, то отмеченное исключение является правильным. Вторая версия, исправленная под этот дизайн:
Если EmailUtil прозрачен , например, может быть, это частный метод, принадлежащий рассматриваемому классу,
IllegalArgumentException
он верен тогда и только тогда, когда его предварительные условия могут быть описаны в документации функции. Это тоже правильная версия:Этот дизайн может быть любым.
ParseException
. Здесь назван метод верхнего уровня,scanEmail
который намекает, что конечный пользователь намеревается отправить неизученное электронное письмо, так что это, вероятно, правильно.IllegalArgumentException
. Хотя «проверка» не отмечена, она перемещается в документ Javadoc, документирующий функцию, которой, как ожидается, клиент будет придерживаться.IllegalArgumentException
если клиент не может заранее сказать, что их аргумент является незаконным, неправильно.Примечание об исключении IllegalStateException : это означает, что «внутреннее состояние этого объекта (частные переменные экземпляра) не может выполнить это действие». Конечный пользователь не может видеть частное состояние, поэтому, грубо говоря, оно имеет приоритет
IllegalArgumentException
в случае, когда клиентский вызов не имеет возможности узнать, что состояние объекта несовместимо. У меня нет хорошего объяснения, когда это предпочтительнее проверенных исключений, хотя такие вещи, как двойная инициализация или потеря соединения с базой данных, которое не восстанавливается, являются примерами.источник