Skip to content

JCommander

h908714124 edited this page Jun 24, 2021 · 86 revisions

Fields become abstract methods

This list-valued parameter from the jcommander documentation

// JCommander: repeatable option
@Parameter(names = "--host", description = "The host")
private List<String> hosts = new ArrayList<>();

would be written like this:

// jbock: repeatable option
@Option(names = "--host", description = "The host")
abstract List<String> hosts();

which makes migration pretty straightforward for repeatable options. Most options however are neither repeatable (multiplicity = 0..*) nor required (multiplicity = 1), but optional (multiplicity = 0..1).

Type change for optional fields

In JCommander, every option or parameter that doesn't set the required = true attribute is considered optional. Like this one:

// JCommander: optional option
@Parameter(names = { "-v", "--verbose" }, description = "Level of verbosity")
private Integer verbose = 1;

If the verbose option is not present in the input array, JCommander injects a default value into the command instance. In this case, the default value is the number 1. If no such explicit default value were defined, Java's null reference would be injected instead.

By contrast, jbock does not inject default values, except when the option type is java.util.Optional or one of its cousins OptionalInt, OptionalLong and OptionalDouble. In particular, jbock never injects null.

Consequentially, if the option's type is Integer, jbock will treat it as a "required option" (multiplicity = 1). There isn't an attribute like JCommander's "required = false" to make it optional anyway.

In order to declare an "optional option" (multiplicity = 0..1) in jbock, the type of the option must change. OptionalInt or Optional<Integer> will work.

For example, the following would look like an "optional option" to jbock:

// jbock: optional option
@Option(names = { "-v", "--verbose" }, description = "Level of verbosity")
abstract OptionalInt verbose();

but this looks like a "required option":

// jbock: required option
@Option(names = { "-v", "--verbose" }, description = "Level of verbosity")
abstract Integer verbose();
Note how similar jbock's required option is to JCommander's optional option. When migrating a non-repeatable option or parameter, ask yourself if it is required or not. Then choose the appropriate type. Since most named option are optional, the correct type will probably be Optional<Something>.
In the "jbock: required option" example, if the primitive type int were to be used instead of Integer, the result would be similar. The type int represents a required option.
Clone this wiki locally