Что делает ключевое слово assert?

Что делает assert? Например в функции:

private static int charAt(String s, int d) {
    assert d >= 0 && d <= s.length();
    if (d == s.length()) return -1;
    return s.charAt(d);
}

person Peiska    schedule 10.06.2010    source источник


Ответы (8)


Если вы запускаете свою программу с -enableassertions (или -ea для краткости), то этот оператор

assert cond;

эквивалентно

if (!cond)
    throw new AssertionError();

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

Например, assert d >= 0 && d <= s.length();, как указано в вашем вопросе, эквивалентно

if (!(d >= 0 && d <= s.length()))
    throw new AssertionError();

(Если вы запускали с -enableassertions, то есть.)


Формально Спецификация языка Java: 14.10. В assert Заявлении говорится следующее:

14.10. Утверждение assert
Утверждение - это оператор assert, содержащий логическое выражение. Утверждение включено или отключено. Если утверждение разрешено, выполнение утверждения вызывает оценку логического выражения и выдается сообщение об ошибке, если выражение оценивается как false. Если утверждение отключено, выполнение утверждения не имеет никакого эффекта.

Где "включен или отключен" управляется переключателем -ea, а "Сообщается об ошибке" означает, что выдается AssertionError.


И, наконец, менее известная особенность assert:

Вы можете добавить : "Error message" следующим образом:

assert d != null : "d is null";

чтобы указать, каким должно быть сообщение об ошибке брошенного AssertionError.


Этот пост был переписан как статья, которую здесь.

person aioobe    schedule 10.06.2010
comment
Согласны, утверждения следует использовать не для подтверждения достоверности аргументов, а для указания сильных предположений. - person whiskeysierra; 11.06.2010
comment
Использование assert для тестирования закрытого метода предварительное условие совершенно верно ИМО. - person Pascal Thivent; 11.06.2010
comment
Использование assert - хороший стиль кодирования, если ответственность за аргументы в пределах допустимого диапазона лежит на клиенте. Как утверждает Бертран Мейер (проектирование по контракту), это допущение позволяет избежать дублирующих проверок. Использование IllegalArgumentException - хороший стиль в общедоступном API. См. Также ответ на связанный вопрос о переполнении стека. - person avandeursen; 03.04.2011
comment
Я вижу assert в java очень похоже на макрос отладки, найденный в c или c ++. Если вы запустите несколько очень больших тестов, вы можете их использовать. Но вы можете не указывать их, когда «запускаете» приложение, и, таким образом, вы получаете более высокую производительность. Я не вижу, чтобы это действительно использовалось для проверки переменных аргументов, но более глубоко в коде, где можно проверить различные переменные. Подобно тому, как мы сделали 4 или 5 петель, из которых ожидалось только 4 при всех условиях. - person R. van Twisk; 23.02.2014
comment
следует ли нам удалить код, содержащий assert, из производственного кода? - person Qbik; 04.07.2016
comment
Как добавить -enableassertions в конфигурацию отладки Android Studio? - person Felix; 09.10.2016
comment
@Qbik Вам не нужно; просто запускайте без -enableassertions в производстве, как упоминалось выше. - person Franklin Yu; 03.01.2017

Если условие не выполняется, будет выброшено AssertionError.

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

http://java.sun.com/j2se/1.5.0/docs/guide/language/assert.html#enable-disable

person Richard Fearn    schedule 10.06.2010

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

person Chris Thompson    schedule 10.06.2010
comment
Это не обязательно приводит к сбою программы. Фактически, вы можете поймать AssertionError, как и любое другое исключение. - person Richard Fearn; 11.06.2010
comment
А поскольку утверждения должны быть явно включены, чтобы иметь какой-либо эффект, их присутствие в производственном коде не повредит. - person meriton; 11.06.2010
comment
Ах, моя ошибка, неужели в C они более хлопотны? Может быть, отсюда я вспоминаю ту парадигму ... - person Chris Thompson; 11.06.2010
comment
Что ж, я должен сказать, что согласен. Утверждения Java не следует использовать в производственном коде. Т.е. клиенту не следует указывать запуск с переключателем -ea. - person aioobe; 11.06.2010

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

Сделайте это очень простым для понимания:

Когда у вас есть подобная ситуация вроде этой:

    String strA = null;
    String strB = null;
    if (2 > 1){
        strA = "Hello World";
    }

    strB = strA.toLowerCase(); 

Вы можете получить предупреждение (отображается желтая линия на strB = strA.toLowerCase ();), что strA может дать значение NULL для strB. Хотя вы знаете, что strB абсолютно не будет нулевым в конце, на всякий случай вы используете assert для

1. Отключить предупреждение.

2. Выдать ошибку исключения, ЕСЛИ произойдет худшее (при запуске приложения).

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

Итак, если вы поставите assert, вот так:

    assert strA != null; //Adding here
    strB = strA .toLowerCase();

вы говорите компилятору, что strA абсолютно не является нулевым значением, он может «мирно» отключить предупреждение. ЕСЛИ он имеет значение NULL (в худшем случае), приложение остановит приложение и выдаст вам ошибку, чтобы найти ее.

person felixwcf    schedule 13.06.2014

Используйте эту версию инструкции assert, чтобы предоставить подробное сообщение для AssertionError. Система передает значение Expression2 соответствующему конструктору AssertionError, который использует строковое представление значения в качестве подробного сообщения об ошибке.

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

JavaDoc

person Jan K.    schedule 10.06.2010

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

В вашем случае он выполняет проверку данных по входящим параметрам, хотя это не мешает клиентам злоупотреблять функцией в будущем. Особенно, если их нет (и не следует) включать в сборку выпуска.

person Zoli    schedule 10.06.2010

Это гарантирует, что выражение вернет истину. В противном случае выдается java.lang.AssertionError.

http://java.sun.com/docs/books/jls/third_edition/html/statements.html#14.10

person Brett Kail    schedule 10.06.2010

Assert выдает ошибку AssertionError, если вы запускаете приложение с включенными утверждениями.

int a = 42;
assert a >= 0 && d <= 10;

Если вы запустите это, скажите: java -ea -jar peiska.jar

Он должен выбросить java.lang.AssertionError

person NoozNooz42    schedule 10.06.2010