1

您可以在此处找到代码示例。 链接到我的 GitHub 项目

在文件 Driver.java 中,可以看到我指定了一个独占的 ArgGroup。我根据文档的理解是默认的多重性是 0..1。文档指出,“默认值为 multiplicity = "0..1",这意味着默认情况下可以省略或指定一个组”。

我也尝试将多重性显式设置为 0..1 但这并没有改变行为。在没有 -al 或 -rl 选项的情况下运行程序,解析会引发 NullPointerException。该框架的行为就像需要其中一个选项一样。这与文档不一致。如果我愿意,我应该可以只使用 -n 选项来运行这个程序。我希望 ArgGroup 完全是可选的。

git hub 链接上的程序是一个功能齐全的 maven 项目,可以克隆、构建和运行。然而,这里是堆栈跟踪。没有指定参数或没有 arg 组。我希望完全没有参数可以打印使用信息。此外,该组的默认多重性应该是 0..1,所以我不应该指定 arg 组中的选项之一。

java.lang.NullPointerException
    at com.shawnfox.java4.concurrency.Driver.call(Driver.java:58)
    at com.shawnfox.java4.concurrency.Driver.call(Driver.java:1)
    at picocli.CommandLine.executeUserObject(CommandLine.java:1743)
    at picocli.CommandLine.access$900(CommandLine.java:145)
    at picocli.CommandLine$RunLast.handle(CommandLine.java:2101)
    at picocli.CommandLine$RunLast.handle(CommandLine.java:2068)
    at picocli.CommandLine$AbstractParseResultHandler.execute(CommandLine.java:1935)
    at picocli.CommandLine.execute(CommandLine.java:1864)
    at com.shawnfox.java4.concurrency.Driver.main(Driver.java:50)
4

1 回答 1

1

感谢您添加堆栈跟踪。我看到它NullPointerException发生在第58 行call的方法中,而不是 picocli 本身。

所以问题不在于 picocli 需要可选 (multiplicity = 0..1) 参数组中的选项,问题在于该call方法假定@ArgGroup-annotated 字段将始终被初始化,即使组中没有选项匹配。这个假设是不正确的。

发生的情况是,如果在命令行上既没有指定-al选项,也没有-rl指定选项,则SynchronizationOptions参数组根本不匹配,因此 picocli 不会实例化SynchronizationOptions对象,并且不会初始化synchOptions第 32 行的字段。

这就是 picocli 解析器如何处理参数组:*例如,对于具有 multiplicity 的组,picocli 将为每个组匹配创建用户对象的实例,并将其添加到带注释的集合/数组字段中。

如果没有匹配的组,则用户对象的实例为零。这允许应用程序准确地检测组是否匹配 - 如果组匹配,应用程序可以依赖于不变量,即对于独占组,只有一个选项匹配并具有值,对于同时出现的group所有选项都匹配并具有来自命令行的值。(如果 picocli 在没有匹配的情况下实例化用户对象,这将是不可能的。)

解决方案是更改应用程序以检查null或初始化synchOptions应用程序中的字段。后者可能是最简单和最干净的。例如,替换:

@ArgGroup(exclusive = true)
SynchronizationOptions synchOptions;

@ArgGroup(exclusive = true)
SynchronizationOptions synchOptions = new SynchronizationOptions();

ThensynchOptions永远不会null使应用程序可以安全地在call方法中引用其字段:

public Void call() {
    if (synchOptions.useReentrantLock) {
        // ...

或者,检查是否synchOptions == nullcall方法中。这允许应用程序检测是否有任何同步选项匹配,如果匹配,则应用程序可以依赖于至少一个布尔字段是true.

于 2019-10-27T07:42:22.570 回答