Я видел этот вопрос, но у меня есть еще несколько вопросов об использовании assert
ключевого слова. Я спорил с несколькими другими программистами об использовании assert
. Для этого варианта использования был метод, который может возвращать нуль, если выполнены определенные предварительные условия. Код, который я написал, вызывает метод, затем утверждает, что он не возвращает ноль, и продолжает использовать возвращенный объект.
Пример:
class CustomObject {
private Object object;
@Nullable
public Object getObject() {
return (object == null) ? generateObject() : object;
}
}
Теперь представьте, что я использую это так:
public void useObject(CustomObject customObject) {
object = customObject.getObject();
assert object != null;
// Do stuff using object, which would throw a NPE if object is null.
}
Мне сказали, что я должен удалить то assert
, что они никогда не должны использоваться в производственном коде, только для тестирования. Это правда?
-ea
или эквивалентный.Objects.requireNonNull
в Java 8).Ответы:
Используйте
Objects.requireNonNull(Object)
для этого.В вашем случае это будет:
Эта функция сделана для целей, которые вы упомянули, т. Е. Явно помечает то, что не должно быть нулем; также в производстве. Большим преимуществом является то, что вы убедитесь, что вы найдете нулевые значения именно там, где они не должны появляться в первую очередь. У вас будет меньше проблем с отладкой, вызванной нулевыми значениями, которые были переданы туда, где их не должно быть.
Еще одним преимуществом является дополнительная гибкость в отношении нулевых проверок в отличие от
assert
. Хотяassert
это ключевое слово для проверки логического значения,Objects.requireNonNull(Object)
оно является функцией и поэтому может быть встроено в код гораздо более гибким и читаемым. Например:Имейте в виду, что
Objects.requireNonNull(Object)
это исключительно для нулевой проверки, гдеassert
обобщается.assert
имеет несколько другие цели в этом отношении, то есть, прежде всего, тестирование Он должен быть включен, чтобы вы могли включить его для тестирования и отключить для производства. В любом случае, не используйте его для производственного кода. Это может замедлить работу приложения с ненужными и сложными проверками, которые предназначены для тестирования. Используйте его для отделения проверок только для проверки от проверок, которые также предназначены для производства.Проверьте официальную документацию для деталей о
assert
.источник
Самое важное, что нужно помнить об утверждениях, это то, что они могут быть отключены, поэтому никогда не предполагайте, что они будут выполнены.
Для обратной совместимости JVM по умолчанию отключает проверку утверждений. Они должны быть явно включены, используя либо аргумент командной строки -enableassertions, либо его сокращение -ea:
Поэтому не стоит полагаться на них.
Поскольку утверждения не включены по умолчанию, вы никогда не можете предполагать, что они будут выполнены при использовании в коде. Поэтому вы всегда должны проверять наличие нулевых значений и пустых необязательных параметров, избегать использования утверждений для проверки входных данных в общедоступном методе и вместо этого использовать исключение без проверки ... В общем, выполняйте все проверки, как если бы утверждения не было.
источник
Конечно, то, что вам говорят, это вопиющая ложь. Вот почему
Утверждения по умолчанию отключены, если вы просто запускаете автономную версию jvm. Когда они отключены, они не занимают места, поэтому они не повлияют на ваше производственное приложение. Тем не менее, они, вероятно, являются вашими лучшими друзьями при разработке и тестировании вашего кода, и большинство бегунов среды тестирования включают утверждения (JUnit делает), поэтому ваш код подтверждения выполняется при запуске ваших модульных тестов, помогая вам обнаружить любые потенциальные ошибки ранее (например, Вы можете добавить утверждения для некоторых проверок границ бизнес-логики, и это поможет обнаружить некоторый код, который использует неподходящие значения).
При этом, как следует из другого ответа, именно по этой причине (они не всегда включены) вы не можете полагаться на утверждения для выполнения некоторых жизненно важных проверок или (особенно!) Поддержания какого-либо состояния.
Для интересного примера того, как вы могли бы использовать утверждения, посмотрите здесь - в конце файла есть метод,
singleThreadedAccess()
который вызывается из оператора assert в строке 201 и предназначен для захвата любого потенциального многопоточного доступа в тестах.источник
Другие ответы уже достаточно хорошо охватывают это, но есть и другие варианты.
Например, у Spring есть статический метод:
org.springframework.util.Assert.notNull(obj)
Есть и другие библиотеки со своими
Assert.something()
методами. Это также довольно просто написать свой собственный.Однако имейте в виду, какие исключения вы выбрасываете, если это веб-сервис. Предыдущий упомянутый метод, например, выбрасывает значение,
IllegalArgumentException
которое по умолчанию в Spring возвращает 500.В случае веб-службы это часто не внутренняя ошибка сервера, и она должна быть не 500, а 400, что является неправильным запросом.
источник
assert
том, чтобы получить немедленный сбой с созданным основным файлом, чтобы вы могли сделать посмертную работу с вашим любимым отладчиком прямо там, где было нарушено условие.assert
бросить. Интересно. Версия C / C ++ не делает этого. Это немедленно поднимает сигнал, что а) убивает процесс, и б) создает дамп ядра. Это делается по причине: отладить такой сбой утверждения очень просто, потому что у вас все еще есть вся информация о стеке вызовов. Определениеassert
вместо того, чтобы генерировать исключение, которое затем может быть намеренно поймано (не) программно, побеждает цель, imho.Throwable
. Их всегда можно поймать. Хорошо это или нет, я не знаю. Я думаю, это зависит Многие Java-программы являются веб-службами, и было бы нежелательно, чтобы они зависали практически по любой причине, поэтому почти все регистрируется и регистрируется. Одна из замечательных вещей - трассировка стека, и этого обычно достаточно, чтобы самостоятельно диагностировать причину исключения или ошибки.Использование утверждений свободно, когда это делает, помогает обнаруживать ошибки программирования, то есть ошибки.
Не используйте assert, чтобы поймать что-то, что может логически произойти, например, плохо отформатированный ввод. Используйте assert только тогда, когда ошибка не устраняется.
Не помещайте никакую производственную логику в код, который запускается, когда проверяется утверждение. Если ваше программное обеспечение хорошо написано, это тривиально, но если это не так, у вас могут быть незначительные побочные эффекты и другое общее поведение с включенными и отключенными утверждениями.
Если в вашей компании «тестирующий код» и «производственный код» выполняют одно и то же, но на разных основах кода (или на разных этапах редактирования), уходите оттуда и никогда не возвращайтесь. Попытка исправить этот уровень некомпетентности, вероятно, пустая трата вашего времени. Если ваша компания не помещает никаких утверждений assert вне кода тестов, пожалуйста, скажите им, что утверждения отключены в производственной сборке, а если нет, исправление этой ошибки теперь является вашим первым приоритетом.
Значение утверждений должно точно использоваться в бизнес-логике, а не только в наборе тестов. Это облегчает создание многих высокоуровневых тестов, которые не должны явно тестировать многие вещи, чтобы пройти через большие фрагменты вашего кода и вызвать все эти утверждения. В некоторых из моих проектов типичные тесты даже ничего не утверждали, они просто предписывали выполнить вычисления на основе конкретного ввода, и это привело к проверке сотен утверждений и обнаружению проблем даже в крошечных кусочках логики.
источник
Вы можете использовать Assert в любое время. Приходят дебаты, когда использовать. Например, в руководстве :
источник