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. 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 for java.util.Optional and 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" to change this.

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

For example, this would be an "optional option" in jbock:

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

but this would be a "required option":

// jbock: required option
@Parameter(names = { "-v", "--verbose" }, description = "Level of verbosity")
abstract Integer verbose();
Note how similar jbock's required option is to the JCommander example. When migrating a non-repeatable option or parameter, ask yourself if it is required or not. Then choose the appropriate type. For a named option, the correct type will probably be Optional<Something>.

In the "required" example, if the primitive type int were to be used instead of Integer, the result would be similar. The generated parser would consider int verbose a required option. jbock does not assume a default value of 0 for an int option, just like it doesn't assume a default value of null for an Integer option.

Clone this wiki locally