我实际上最终采取了不同的方法。能够直接分配给实际类型的字段对我的应用程序很有帮助(因为我们正在开发一项功能,您可以在其中“发现”接受各种类型参数的命令,因此使该字段成为实际类型可以做到这一点反向查找更容易)。
所以我最终这样做了:
static class DoubleConverter implements ITypeConverter<Double> {
public Double convert(String value) throws Exception {
if(value.isEmpty()) return Double.NaN; // this is a special value that indicates the option was present without a value
return Double.valueOf(value);
}
}
@Option(names = {"-e", "--epsilon"}, arity="0..1", description="Acceptable values: [0, 1] default: 0.1", converter=DoubleConverter.class)
Double epsilon;
基本上,我使用一个转换器来存储一个特殊值(在这种情况下为 NaN,因为我们最终使用了一个双精度值)来指示该选项存在时没有值(这与它根本不存在不同,在这种情况下它将为空)。
run()然后按照您的建议在方法中执行验证和其他行为:
@Override
public void run() {
// null indicates the option was not present, so do nothing
if(epsilon != null) {
// NaN indicates the option was present but with no value, which means we should print the current value
if(epsilon.equals(Double.NaN)) {
// print current value from the application
printEpsilonValue();
}
else {
// validate value
if(epsilon < 0.0 || epsilon > 1.0) {
throw new ParameterException(spec.commandLine(), "Invalid parameter value");
} else {
// set the value in the application
setEpsilonValue(episilon);
}
}
}
}
我无法使用变量在描述中指定默认值,因为在这种情况下实际的默认值需要为空。不过,这是一个小小的牺牲。
我意识到这是一个不寻常的情况,但支持这种选项(非布尔值,arity 0..n)可能会很好,而不需要求助于特殊值。也许能够指定另一个字段作为布尔值,指示选项是否存在。那么也不需要自定义转换器,并且可能仍然可以指定默认值(即,在这种情况下,Double 字段将设置为默认值,但如果该选项不存在,则相应的布尔字段将为假,因此应用程序将知道不使用 Double 的值)。