Ключевое слово assert (проверка) появилось в Java 1.4. Мне кажется, многие до сих пор стараются его избегать, или заворачивать в утилитные статические методы с возможностью быстро поменять assert condition : message;
на
if (!condition)
throw new AssetionError(message);
по всему коду. Кто-то боится, что проверки недостаточно надежные, и если кто-то забудет их включить, какие-то баги останутся незамеченными. Кто-то, наоборот, маниакально думает о производительности: если кто-то включит проверки для подсистемы/библиотеки, написанной ребятами из первой группы, и забудет исключить пакеты или классы «производительной» библиотеки, исполнение будет замедленно бесполезными вычислениями.
Хотя, по-моему, ничего страшного в проверках нет, их можно и нужно расставлять по коду как можно щедрее. Во-первых, как я уже упомянул (но для кого-то это может оказаться в новинку), проверки можно гибко настраивать (включать/отключать в пакетах и отдельных классах) как из командной строки при запуске JVM, так и программно (через ClassLoader), так что если вы вдруг захотите включить проверки в одной системе и выключить — в другой, это уж точно решаемая проблема.
Во-вторых, иногда хочется проверять не тривиальные условия вроде какая-то булева переменная == false или true
, а поддерживать некоторое проверочное состояние внутри класса и сверяться с ним в методах. С помощью трюка с assert
можно добиться этого практически бесплатно при исполнении с отключенными проверками.
Трюк прост — инициализация и обновление проверочного состояния выносится в методы, которые по смыслу ничего не возвращают (void
), а в коде — boolean
и всегда true
. Эти методы вызываются «через» assert
. То есть, когда проверки для класса отключены, методы не вызываются, проверочное состояние не инициализируется и не обновляется, и в накладных расходах остается только одна null
-ссылка в памяти объекта.
Пример:
import java.util.HashSet;
import java.util.Set;
public final class MyCoolSet<E> {
private Object[] coolStorage;
private transient Set<E> referenceSet;
public MyCoolSet() {
// ... init cool storage
assert initReferenceSet();
}
private boolean initReferenceSet() {
referenceSet = new HashSet<>();
return true;
}
public int size() {
// return the cool size
return 42;
}
public boolean add(E e) {
// .. add an element to the cool storage
boolean added = true;
assert addToReferenceSet(e);
return added;
}
private boolean addToReferenceSet(E e) {
referenceSet.add(e);
checkSize();
return true;
}
private void checkSize() {
assert referenceSet.size() == size() :
"Cool size diverged from reference size";
}
public boolean remove(Object o) {
// ... remove an element from the cool storage
boolean removed = true;
assert removeFromReferenceSet(o);
return removed;
}
private boolean removeFromReferenceSet(Object o) {
referenceSet.remove(o);
checkSize();
return true;
}
}
Автор: leventov