Использование assert


Другим относительно новым дополнением к Java является ключевое слово assert. Оно используется во время разработки программ для создания так называемых утверждений (assertion), представляющих собой условия, которые должны быть истинными во время выполнения программы. Например, вы можете иметь метод, который всегда возвращает положительное целое значение. Вы можете тестировать его утверждением, что возвращаемое значение больше нуля, используя оператор assert. Во время выполнения, если условие действительно истинно, то никаких других действий не выполняется. Однако если условие окажется ложным, будет возбуждено исключение AssertionError. Утверждения часто применяются при тестировании для верификации того, что некоторое ожидаемое условие действительно выполняется. В коде окончательной версии они, как правило, не. присутствуют.

Ключевое слово assert имеет две формы. Первая выглядит так:

assert condition;

Здесь condition — выражение, которое должно при вычислении дать булевский результат. Если результат равен true, то утверждение истинно, и никаких действий не выполняется. Если же условие дает false, значит, произошел сбой и возбуждается объект исключения по умолчанию AssertionError.

Вторая форма assert выглядит следующим образом:

assert condition:expr;

В этой версии expr — значение, которое передается конструктору AssertionError. Это значение преобразуется в строковую форму и отображается, если утверждение ложно. Обычно вы специфицируете строку для ехрг, но разрешено любое выражение, отличное от void, до тех пор, пока оно допускает осмысленное строковое преобразование.

Ниже показан пример использования assert. В нем осуществляется проверка того, что возвращаемое значение getnum () положительно.

// Демонстрация assert.
class AssertDemo {
static int val = 3; // Возвращает целое.
static int getnum() {
return val--;
}
public static void main(String args[]) {
int n;
for(int i=0; i < 10; i++) {
n = getnum();
assert n > 0; // произойдет сбой, если n == 0
System.out.println("n равно " + n) ;
}
}
}

Чтобы включить проверку утверждений во время выполнения, вы должны указать опцию -еа. Например, чтобы сделать это для AssertDemo, выполните следующую команду:

java -еа AssertDemo

После компиляции и запуска, как показано выше, программа выдает следующий результат:

n равно 3
n равно 2
n равно 1

Exception in thread "main" java.lang.AssertionError
at AssertDemo.main(AssertDemo.java:17)
Исключение в потоке "main" java.lang.AssertionError в AssertDemo.main(AssertDemo.java:17)

В main () выполняются повторяющиеся вызовы метода getnum (), который возвращает целое значение. Возвращаемое значение getnum () присваивается п и затем тестируется оператором assert:

assert n > 0; // произойдет сбой, если n == 0

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

Как объяснялось, вы можете специфицировать сообщение, отображаемое при сбое утверждения. Например, если вы подставите

assert n > 0 : "n отрицательное!";

в утверждение из предыдущей программы, то будет выдан такой результат:

n равно 3
n равно 2
n равно 1

Exception in thread "main" java.lang.AssertionError : n отрицательное! at AssertDemo.main(AssertDemo.java:17)

Один момент, важный для понимания утверждений — это то, что вы не должны полагаться на них для выполнения каких-либо действий программы. Причина в том, что нормальный код окончательной версии будет выполняться с отключенным механизмом проверки утверждений. Например, рассмотрим следующий вариант предыдущей программы:

// Плохой способ применения assert! ! !
class AssertDemo {
// получить генератор случайных чисел
static int val = 3; // Возвращает целое.
static int getnum() {
return val--;
}
public static void main(String args[j) {
int n = 0;
for(int i=0; i < 10; i++) {
assert (n = getnum()) > 0; // Плохая идея!
System.out.println("n is " + n) ;
}
}
}

В этой версии программы вызов getnum () перемещен в оператор assert. Хотя это хорошо работает, когда механизм проверки утверждений включен, его отключение приведет к неправильной работе программы, потому что вызов getnum () никогда не произойдет! Фактически п теперь должно быть инициализировано, поскольку компилятор распознает ситуацию, что значение может не быть присвоено в операторе assert.

Утверждения — хорошее нововведение в Java, потому что оно упрощает тип проверки ошибок, который часто используется во время разработки. Так, например, до появления assert, если вы хотели проверить, что п имеет положительное значение в приведенной выше программе, то должны были написать примерно следующую последовательность кода:

if(n < 0) {
System.out.println("п отрицательное! ") ;
return; // или возбудить исключение
}

Для применения assert нужна только одна строка кода. Более того, вам не придется удалять строки с assert из окончательного варианта кода.