如何在picocli中将接口的字段设置为命令行选项?
问题根因
你的写法不生效是Java语法特性导致的,和picocli本身功能无关:
Java 接口中定义的成员变量默认会被隐式标记为public static final常量,无法被实例修改赋值。而picocli的参数注入逻辑是给命令类的实例属性赋值,自然无法给常量注入用户输入的参数,所以会触发异常。
picocli本身完整支持在接口、父类上定义公共选项,只要写法符合规范即可,以下是两种常用的重构方案:
方案1:使用抽象基类存放公共属性(推荐,写法更简洁)
直接把公共选项定义在抽象父类中,命令子类继承父类即可继承所有选项配置:
// 公共抽象父类 public abstract class BaseCommand { // 注意picocli的选项注解是单数@Option,不是复数@Options @Option(names = "-n1") public int num1; @Option(names = "-n2") public int num2; } // ClassA继承父类即可,无需重复定义属性 @Command(name = "-classA") class A extends BaseCommand { public void testA(){ System.out.println("class A Testing"); System.out.println(num1 + num2); } } // ClassB同理 @Command(name = "-classB") class B extends BaseCommand { public void testB(){ System.out.println("class B Testing"); System.out.println(num1 + num2); } }
方案2:使用接口定义公共选项
如果必须用接口实现,可以把@Option注解加在接口的抽象getter方法上,picocli会自动识别并把参数注入到实现类的对应属性中:
interface MyInterface { @Option(names = "-n1") int getNum1(); @Option(names = "-n2") int getNum2(); } // 命令类实现接口即可 @Command(name = "-classA") class A implements MyInterface { public int num1; public int num2; @Override public int getNum1() { return num1; } @Override public int getNum2() { return num2; } public void testA(){ System.out.println("class A Testing"); System.out.println(num1 + num2); } }
注意事项
picocli 4.x及以上版本默认支持注解从父类、接口继承,不需要额外配置即可正常生效。
内容的提问来源于stack exchange,提问作者Leo Ha
相关产品推荐
相关产品推荐

