首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法解释的Singleton / Picocli行为

无法解释的Singleton / Picocli行为
EN

Stack Overflow用户
提问于 2020-05-08 15:04:11
回答 1查看 133关注 0票数 1

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

代码语言:javascript
复制
public class AppData implements Callable<Integer> {
    private static AppData appData = new AppData();

    private AppData() {
        System.out.println("AppData-Constructor");
    }

    public static AppData getInstance() {
        return appData;
    }

    @Override
    public Integer call() throws Exception { // your business logic goes here...
        return 0;
    }

    private boolean _validate;

    public boolean validate() {
        return _validate;
    }

    @Option(names = { "--validate" }, description = "", defaultValue = "false", hidden = false, interactive = false, paramLabel = "", required = false, type = boolean.class)
    public void set_validate(boolean validate) {
        System.out.println("Set Validate: " + validate);
        this._validate = validate;

        if(validate)
        {
            System.out.println("\nBeginne Programmvalidierung\n");
            Path tmp = null;
            try {
                // Doing some validation stuff
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

如你所见,我的班是单身学生。注释来自picoli,我使用它解析命令行参数。System.out-calls用于调试。我无法解释这种行为:

当我以"-h“作为参数开始我的应用程序时,我的帮助打印得很好。System.out.println显示创建了单例,并使用默认值调用了set_validate()。但当我使用--validate作为参数时,这种情况就改变了。

由于某些原因,构造函数和默认集在一行中被调用两次。在此之后,用set_validate()调用true (正如它应该的那样)。但是,第一个调用似乎设置了静态实例变量,而使用true的最后一个调用是在第二个实例上完成的(我的理论)。因此,当我从我的main方法(在另一个类中)检查我的单例实例上的_validatevalidate()的状态时,我得到了false,因为它没有在正确的实例中设置。

我用搜索引擎检查:

  1. 除了静态单例实例(正如预期的那样,因为它是私有的),构造函数不会在任何地方调用。
  2. 除了我发布的代码之外,任何地方都不能访问_validate
  3. set_validate()在任何地方都不被调用。只有Picocli叫它。

我不知道下一步该查什么。有什么想法吗?

问候

托斯滕

编辑:AppData是保存数据的多个类之一。它们都是为Picocli收集的一个大类,如下所示:

代码语言:javascript
复制
class Data
{
    @AddGroup(...)
    AppData appData = AppData.getInstance();

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

    @AddGroup(...)
    BarData barData = BarData.getInstance();
}

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

代码语言:javascript
复制
Data data = new Data();
CommandLine cmd = new CommandLine(data);
cmd.parseArgs(args);
EN

回答 1

Stack Overflow用户

发布于 2020-05-09 02:12:36

我怀疑(但只能猜测,因为没有显示代码的这一部分) AppData是另一个命令的子命令,或者应用程序使用picocli,如下所示:

代码语言:javascript
复制
int exitCode = new CommandLine(AppData.class).execute(args);

在这两种情况下,picocli将使用反射创建AppData实例。由picocli创建的实例是从命令行值中填充的实例。这是一个不同于AppData::getInstance返回的实例。

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

代码语言:javascript
复制
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_validate方法?

从4.2版开始,picocli将首先使用默认值调用@Option-annotated方法,然后再解析命令行参数。因此,首先用默认值调用set_validate方法,然后使用命令行上指定的值再次调用。

(从Version4.3(即将发布)开始,缺省值将在命令行上只有在未指定值的情况下才设置,因此在Version4.3中,set_validate方法只会被调用一次。)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61682124

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档