Commons CLIとArgs4jを比べてみる

JavaCUIツールを作成するとき、Commons CLIArgs4jというライブラリがあります*1
で、どっちを使うのがいいの?ということがあると思いますので、それぞれの特徴を述べたいと思います。
まずそれぞれの最新は、Commons CLIはバージョン1.1、args4jはバージョン2.0.9になります。
Commons CLIでは2.0が開発中のようですが、正式版はまだなのでここでは取り上げません。
以下、表にしてみます。

比較表

Commons CLI Args4j 備考
Java 1.3以上 5以上
引数のバインド Optionオブジェクト アノテーション
ロングネーム
パーサの変更 × Commons CLIのパーサはBasicとGNUPosixの3種類から選べます。
使用例出力

以下、それぞれ使用したコードと実行結果を記載します。

コード例

import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

public class CLI {
	public static void main(String[] args) {
		Options options = new Options();
		options.addOption("i", true, "user id");
		options.addOption("n", true, "user name");
		options.addOption("d", "debug", false, "debug option");
		options.addOption(OptionBuilder
               		.withArgName("option")
               	 	.hasArg()
                		.withDescription("optional args")
                		.isRequired(false)
               	 	.create("o") );
		
		String[] args1 = {"-i", "317", "-n", "cactusman", "--debug"};
		CommandLineParser parser = new BasicParser();
		CommandLine cl = null;
		try {
			cl = parser.parse(options, args1);
		} catch (ParseException e) {
			e.printStackTrace();
			return;
		}
		
		HelpFormatter formatter = new HelpFormatter();
        	formatter.printHelp("CLI", options, true);
        
        	int id = Integer.parseInt(cl.getOptionValue("i"));
        	String name = cl.getOptionValue("n");
        	boolean isDebug = Boolean.parseBoolean(cl.getOptionValue("d"));
        	String optional  = cl.getOptionValue("o");
        	System.out.println("ID:" + id);
		System.out.println("Name:" + name);
		System.out.println("Debug:" + isDebug);
		System.out.println("Optional:" + optional);
	}
}
    • 結果
usage: CLI [-d] [-i <arg>] [-n <arg>] [-o <option>]
 -d,--debug    debug option
 -i <arg>      user id
 -n <arg>      user name
 -o <option>   optional args
ID:317
Name:cactusman
Debug:false
Optional:null


  • Args4j
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.Option;

public class Args4j {
	@Option(name="-i", metaVar="id", usage="user id")
	private int id;
	
	@Option(name="-n", metaVar="name", usage="user name")
	private String name;
	
	@Option(name="-d", aliases="--debug", usage="debug option")
	private boolean isDebug;
	
	@Option(name="-o", usage="optional args", required=false)
	private String optional;
	
	public static void main(String[] args) {
		Args4j args4j = new Args4j();
		String[] args1 = {"-i", "317", "-n", "cactusman", "--debug"};
		CmdLineParser parser = new CmdLineParser(args4j);
		try {
			parser.parseArgument(args1);
		} catch (CmdLineException e) {
			e.printStackTrace();
			return;
		}
		
		parser.printSingleLineUsage(System.out);
		System.out.println();
		parser.printUsage(System.out);
		System.out.println();
		
		System.out.println("ID:" + args4j.id);
		System.out.println("Name:" + args4j.name);
		System.out.println("Debug:" + args4j.isDebug);
		System.out.println("Optional:" + args4j.optional);
	}
}
    • 結果
[-d (--debug)] [-i id] [-n name] [-o VAL]
 -d (--debug) : debug option
 -i id        : user id
 -n name      : user name
 -o VAL       : optional args

ID:317
Name:cactusman
Debug:true
Optional:null

感想

使用感としてはアノテーションで記述するArgs4jのほうが記述量が少なく、使いやすいのではと思いました。
実際、postterではそれぞれのサブコマンドごとに引数が少し違う、というものを作るのに継承が使えて大変見やすくなっています。
これをCommons CLIでやろうと思えばできますが、記述量が増えて見通しも悪くなるのではないかと思います。
ただ、Args4jではPosixパターンのパーサはありませんし、Java5以上でないと使えないという制限はあります。
こういうところで好みが大きく変わりますが、自分としてはArgs4jのほうが好きですね。

*1:もちろん他にもありますが