Java 无法解释的单态/Picocli行为

Java 无法解释的单态/Picocli行为,java,singleton,picocli,Java,Singleton,Picocli,我正在写一些代码,我不知道我的bug是怎么回事。我希望这里有人能给我一些答案。这是我的代码(相关部分): 在我的主要方法中是这样使用的: Data data = new Data(); CommandLine cmd = new CommandLine(data); cmd.parseArgs(args); 我怀疑(但只能猜测,因为这部分代码没有显示)AppData是另一个命令的子命令,或者应用程序使用picocli如下: class Data { @AddGroup(...)

我正在写一些代码,我不知道我的bug是怎么回事。我希望这里有人能给我一些答案。这是我的代码(相关部分):

在我的主要方法中是这样使用的:

Data data = new Data();
CommandLine cmd = new CommandLine(data);
cmd.parseArgs(args);
我怀疑(但只能猜测,因为这部分代码没有显示)AppData是另一个命令的子命令,或者应用程序使用picocli如下:

class Data
{
    @AddGroup(...)
    AppData appData = AppData.getInstance();

    @AddGroup(...)
    FooData fooData = FooData.getInstance();

    @AddGroup(...)
    BarData barData = BarData.getInstance();
}
int exitCode = new CommandLine(AppData.class).execute(args);
在这两种情况下,picocli都将使用反射创建
AppData
的实例。picocli创建的实例是从命令行值填充的实例。这与
AppData::getInstance
返回的实例不同

确保只有一个实例的一种方法是将singleton实例传递给picocli。例如:

AppData singleton = AppData.getInstance();
int exitCode = new CommandLine(singleton).execute(args);

System.out.println("validate=" + singleton.validate());
(如果
AppData
是一个子命令,那么还有其他方法可以访问picocli创建的实例,比如注入picocli模型,并调用
CommandSpec::userObject()
getter获取
AppData
实例。)

现在,另一个问题是:
set\u validate
方法为什么会被调用两次

从4.2版开始,picocli将在解析命令行参数之前,首先调用带有默认值的带注释的方法。因此,首先使用默认值调用
set\u validate
方法,然后使用命令行上指定的值再次调用该方法


(从4.3版(即将发布)开始,默认值将出现在命令行上,因此从4.3版开始,
set\u validate
方法将只调用一次。)

如果您让构造函数生成stacktrace并将其写入控制台,那么您应该能够在调用构造函数时看到调用它的内容。也许这会给你一个提示。我不熟悉Picoli,但它似乎必须构造自己的注释类实例,即使它有一个私有构造函数。我想知道如果您使用枚举而不是带有静态字段的类来实现单例模式,会发生什么情况。@NathanHughes我试过了。据我所知,第二个Instancene是使用反射创建的,正如Remko的回答所说。谢谢你的回答。我按建议在stacktrace上呆呆地看着,这表明正在使用反射。但我实际上把一个物体传给了皮科利。我将编辑我的问题以添加此信息。谢谢。stacktrace也可能有用。一个能够重现问题的小型可运行程序是理想的。
AppData singleton = AppData.getInstance();
int exitCode = new CommandLine(singleton).execute(args);

System.out.println("validate=" + singleton.validate());