Спасибо за добавление трассировки стека. Я вижу, что NullPointerException
происходит в методе call
в строке 58 , а не в самой picocli.
Таким образом, проблема не в том, что picocli требуются параметры в необязательной группе аргументов (кратность = 0..1
), проблема в том, что метод call
предполагает, что аннотированное поле @ArgGroup
всегда будет инициализировано, даже если ни одна опция в группе не совпадает. Это предположение неверно.
Что происходит, если ни параметр -al
, ни параметр -rl
не указаны в командной строке, то для группы аргументов SynchronizationOptions
вообще нет соответствия,поэтому picocli не будет создавать экземпляр объекта SynchronizationOptions
, а поле synchOptions
в строке 32 не будет инициализировано.
Так работает анализатор picocli с группами аргументов: например, для группы с кратностью *
picocli создаст экземпляр объекта пользователя для каждого совпадения группы и добавит его в аннотированную коллекцию /поле массива.
Если не найдено ни одной группы, экземпляры пользовательского объекта будут нулевыми. Это позволяет приложению точно определять, была ли группа сопоставлена или нет - и если группа соответствует , приложение может полагаться на инвариант, который для исключительной группы был только один параметр соответствует и имеет значение, а для совместной группы все параметры были сопоставлены и имеют значения из командной строки. (Это было бы невозможно, если picocli создал экземпляр пользовательского объекта без совпадения.)
Решение состоит в том, чтобы изменить приложение, чтобы либо проверять наличие null
, либо инициализировать поле synchOptions
в приложении. Последнее, наверное, самое простое и чистое. Например, замените:
@ArgGroup(exclusive = true)
SynchronizationOptions synchOptions;
на
@ArgGroup(exclusive = true)
SynchronizationOptions synchOptions = new SynchronizationOptions();
Тогда synchOptions
никогда не будет null
, поэтому приложение может безопасно ссылаться на свои поля в методе call
:
public Void call() {
if (synchOptions.useReentrantLock) {
// ...
Либо проверьте, есть ли synchOptions == null
в методе call
. Это позволяет приложению обнаруживать, был ли сопоставлен какой-либо из параметров синхронизации, и если оно было сопоставлено, приложение может полагаться на тот факт, что хотя бы одно из логических полей имеет значение true
.