Спешим поделиться интересной ошибкой, которую нашел наш анализатор. В примере ошибка из проекта OpenIDE:
public final class UsageType { .... public static final UsageType DELEGATE_TO_ANOTHER_INSTANCE_PARAMETERS_CHANGED = new UsageType( UsageViewBundle.messagePointer( "usage.type.delegate.to.another.instance.method.parameters.changed" ) );
private static final Logger LOG = Logger.getInstance(UsageType.class);
public UsageType(@NotNull Supplier<....> nameComputable) { myNameComputable = nameComputable; if (ApplicationManager.getApplication().isUnitTestMode()) { String usageTypeString = myNameComputable.get(); if (usageTypeString.indexOf('{') != -1) { LOG.error(....); } } } .... }
Срабатывание анализатора PVS-Studio: V6050 Class initialization cycle is present. Initialization of 'DELEGATE_TO_ANOTHER_INSTANCE_PARAMETERS_CHANGED' appears before the initialization of 'LOG'. UsageType.java 46
Анализатор говорит, что мы имеем дело с циклической зависимостью при инициализации статических полей. Снова не самый очевидный момент, связанный с нюансами языка Java. Для инициализации поля DELEGATE_TO_ANOTHER_INSTANCE_PARAMETERS_CHANGED используется конструктор. А в нём мы обращаемся к логгеру LOG.
Всё дело в том, что поля инициализируются в порядке их объявления. Как вы можете видеть, DELEGATE_TO_ANOTHER_INSTANCE_PARAMETERS_CHANGED располагается выше LOG, т.е. инициализируется раньше. Как следствие, LOG на момент исполнения конструктора будет равен null, и при обращении к нему мы столкнёмся с NPE.
Исправление, как и в большинстве случаев выше, будет донельзя простым. Нужно просто разместить объявление LOG выше, чем DELEGATE_TO_ANOTHER_INSTANCE_PARAMETERS_CHANGED.
Не совершай такую ошибку в своем проекте! А узнать о других багах из проекта можно по этой ссылке 🔗