S-JIS[2022-09-07/2022-09-14] 変更履歴

JCommander Parameter

JCommanderの@Parameterのメモ。


概要

JCommanderでは、コマンドラインパラメーターを解析 した結果の値を入れるクラスを、ユーザープログラマーが用意する。
そのクラスでは、フィールドに@Parameterアノテーションを付けて、コマンドラインパラメーターを定義する。

※全フィールドに影響する設定は、@Parametersアノテーションで行う。


import com.beust.jcommander.Parameter;
public class MyArgument {

    @Parameter(names = { "-n", "--name" }, description = "user name")
    private String name = "hishidama";

    @Parameter(names = { "-f", "--file" }, description = "file")
    private Path file;

    public String getName() {
        return this.name;
    }

    public Path getFile() {
        return this.file;
    }
}

@Parameterアノテーションを付けるフィールドの可視性は何でもいい。
リフレクションで値が読み書きされるので、privateフィールドでもいい(実行環境のセキュリティー設定で「privateにアクセス可能」にする必要はあるが、通常はアクセス可能))

フィールドのデータ型はString以外でも良い。
値はその型に変換される。数値やbooleanの他、列挙型やURI・Path等に対応している。
独自のConverterを作ることも出来る模様。

フィールドに初期値を持たせると、デフォルト値になる。
usage()でもデフォルト値として表示される)

なお、データ型にプリミティブ型(intやboolean等)を使うと、usage()で常にデフォルト値が表示されてしまう。
ラッパークラス(IntegerやBoolean等)を使えば(初期値をnullにしておけば)デフォルト値は表示されない。


Parameterの設定内容

設定名 デフォルト値 説明
names String[] {}
names = "-f"
names = { "-f", "--file" }
パラメーター名。
名前の無いパラメーター
description String 空文字列
description = "file"
パラメーターの説明。
usage()で表示される。
descriptionKey String 空文字列   @ParametersのresourceBandleから説明文を取得する為のキーらしい。
required boolean false
required = true
必須パラメーターかどうか。
trueにすると、必須になる。
必須の場合、フィールドの初期値(デフォルト値)を定義していても、パラメーターが指定されていなかったらエラーになる。
arity int -1
arity = 1
パラメーターの後に指定する値の個数。
デフォルトは、booleanだと0個で、それ以外は1個。
2個以上にするときは、フィールドのデータ型をListにする。
arityの例
variableArity boolean false
variableArity = true
trueにすると、パラメーターの後に複数個(個数不定)の値を指定できる。→
password boolean false    
echoInput boolean false    
converter Class      
listConverter Class      
validateWith Class      
validateValueWith Class      
splitter Class     パラメーターの後続の値を区切って複数の値にするクラス。
デフォルトでは、カンマで区切る。
forceNonOverwritable boolean false    
help boolean false
help = true
ヘルプコマンドかどうか。→ヘルプの例
order int -1   usage()で表示するときの順序。[2022-09-14]
連番である必要はない。
指定が無いときはパラメーターのアルファベット順になるっぽい。
hidden boolean false   usage()に表示する(隠す)かどうか。
trueにすると、そのパラメーターはusage()で表示されなくなる。

名前の無いパラメーターの例

データを受け取るクラスの中のひとつのフィールドだけ、名前の無いパラメーター(@Parameterのnamesを書かないフィールド)を定義することが出来る。
そこには、名前無しで列挙されたパラメーター(main parameter)が入ってくる。

public class MyArgument {
    〜

    @Parameter(description = "<main1> <main2>...") // no names
    private List<String> mainParameterList;

    public Optional<String> findMainParameter(int index) {
        if (mainParameterList != null && index < mainParameterList.size()) {
            return Optional.of(mainParameterList.get(index));
        }
        return Optional.empty();
    }
}

実行例

java -cp 〜 JCommanderExample --name hishidama a b c

→mainParameterListにa, b, cが入る。


真偽値の例

フィールドのデータ型をbooleanにすることは出来るが、usage()で表示したときに「Default: false」と表示されてしまう。
データ型をBoolean(ラッパークラス)にしておけば、デフォルト値は表示されなくなる。

public class MyArgument {
    〜

    @Parameter(names = { "--on" }, description = "switch on")
    private Boolean on;

    public boolean isOn() {
        return (this.on != null) && this.on;
    }
}

ヘルプはboolean型でもusage()でデフォルト値は表示されない


また、真偽値は、デフォルトではパラメーターの後続に値を書かないが、arityを1にすればtrue/falseを渡せるようになる。

コーディング例 引数の例 結果
@Parameter(names = "b")
private boolean b; 
-b
b=true
 
b=false
@Parameter(names = "b0", arity = 0)
private boolean b0; 
-b0
b0=true
 
b0=false
@Parameter(names = "b1", arity = 1)
private boolean b1; 
-b1 true
b1=true
-b1 false
b1=false

引数の個数を指定する例

arityで、パラメーターの後に続く値の個数を指定する。[2022-09-13]
値の個数が不定な場合は、variableArityを指定する。

複数個の値を受け取るときはデータ型をListにする。
独自クラスで受け取ることも出来る。(独自クラスのフィールドに@SubParameterアノテーションを付ける)

  コーディング例 引数の例 結果 備考
引数1個
@Parameter(names = "-s1", arity=1)
private List<String> s1; 
-s1 a b c
s1=[a]  
引数2個
@Parameter(names = "-s2", arity=2)
private List<String> s2;
-s2 a b c

 

s2=[a, b]  
引数可変個
@Parameter(names = "-sv", variableArity=true)
private List<String> sv;

 

-sv a b c
sv=[a, b, c]  
-sv a b -s1 c
sv=[a, b]
s1=[c]
 
引数を受け取るクラス
import com.beust.jcommander.SubParameter;
public class MyPair {
    @SubParameter(order = 0)
    public String key;

    @SubParameter(order = 1)
    public String value;
}
@Parameter(names = "-p", arity=2)
private MyPair p;
-p a b c
p.key=a
p.value=b
フィールドがpublicでないとエラーになる。
(ver 1.82)
引数の直後に値
import com.beust.jcommander.DynamicParameter;
@DynamicParameter(names = "-D")
Map<String, String> d = new HashMap<>();
-Da=1 -D b=2
d={a=1, b=2} データ型はMap。
インスタンスも与える必要がある。
値は「K=V」の形式のみ有効。

ヘルプの例

よくあるアプリケーションでは、「-?」や「--help」でヘルプ(使用方法)が表示される。
JCommanderを使う場合でも、これらは自分で実装する必要がある。

class MyArgument {

    @Parameter(names = { "-?","--help" }, description = "print usage", help = true)
    private boolean help;

    public boolean isHelp() {
        return this.help;
    }
}
    var argument = new MyArgument();
    var commander = JCommander.newBuilder().addObject(argument).build();
    commander.parse(args);

    if (argument.isHelp()) {
        commander.usage(); // 使用方法(パラメーターの種類)を表示
        System.exit(0);
    }

@Parameterのhelpをtrueにしておくと、多少他と異なる挙動をする。


JCommander目次へ戻る / Javaへ戻る / 技術メモへ戻る
メールの送信先:ひしだま