项目中有一些用java写成的可执行的工具,需要调用者传入大量的参数。最开始,我使用的是最传统的方式,直接一个传入参数数组,于是有如下这么壮观的代码:

public static void main(String[] args) {
    String aaa = args[0];
    String bbb = args[1];
    String ccc = args[2];
    String ddd = args[3];
    String eee = args[4];
    String fff = args[5];
    String ggg = args[6];
    String hhh = args[7];
    // do something with these arguments
}

调用者:

java MyTool hello world1 world2 world3 world4 world5 world6 world7

客户同事拿去用后,感觉十分不便,向我抱怨。原来他在写脚本调用的时候,必须反复查看我的java源代码,才知道每个参数是做什么的。写完之后,下次需要修改的时候,又忘了还得来查。而且参数顺序还不能错,个数也不能多不能少,总之就是很麻烦。

我也认识到这个问题确实存在,便问客户同事有没有什么好办法,他给了我这样的例子:

public static void main(String[] args) {
    String aaa = System.getProperty("aaa");
    String bbb = System.getProperty("bbb");
    String ccc = System.getProperty("ccc");
    String ddd = System.getProperty("ddd");
    String eee = System.getProperty("eee");
    String fff = System.getProperty("fff");
    String ggg = System.getProperty("ggg");
    String hhh = System.getProperty("hhh");
    // do something with these arguments
}

调用者:

java -Daaa=hello -Dbbb=world1 -Dccc=world2 -Dddd=world3 -Deee=world4 -Dfff=world5 -Dggg=world6 -Dhhh=world7 MyTool

客户同事的意思是,这种做法可以“完美”的解决他提到的那几个不便之处,比如:

  • -D后面的参数名可用于提醒参数的意思
  • 顺序怎么写都行
  • 如果哪个参数是可选的,可以直接删除即可

虽然我第一感觉是“竟然敢用这种方式来传参数!”,但一时之间竟想不出什么话来反对,因为他这种方式能做到的,我那种方式的确做不到。

细想一下,这两种方式倒是相当互补,我有你无,我无你有。虽然相比起来,我觉得后者问题更多,因为它会污染System属性环境,更容易产生一些不可预料的问题,但也不失为一种有思考价值的方案。

然后,我想到了这样一种试图结合两者优点的方案:

public static void main(String[] args) {
    Map map = new HashMap();
    for(int i=0; i
        map.put(args[i], args[i+1]);
    }
    String aaa = map.get("-aaa");
    String bbb = map.get("-bbb");
    String ccc = map.get("-ccc");
    String ddd = map.get("-ddd");
    String eee = map.get("-eee");
    String fff = map.get("-fff");
    String ggg = map.get("-ggg");
    String hhh = map.get("-hhh");
    // do something with these arguments
}

调用者:

java MyTool -aaa hello -bbb world1 -ccc world2 -ddd world3 -eee world4 -fff world5 -ggg world6 -hhh world7

看起来似乎清楚了一些,虽然更长了一点。现在,它也可以:

  • 参数列表中有用作提示参数
  • 顺序怎么写都行
  • 如果有可选参数,直接删除对应项

而且不污染System属性环境,相比前面的-D方案,要稍好一些。

只能做到这个程度了吗?看上面的三种方案,实际上都存在着一些问题,需要写更多代码:

  1. 打印usage
  2. 对参数进行检查,如果有缺少的或不合理的,要提示错误

这些缺失的工作实际上相当烦琐,让我们的代码更加混乱,却又不可或缺。

有没有优雅一些的方式呢?答案是有,我们可以利用java的annotation去描述我们的参数,使用这些信息对参数进行验证、取值以及打印使用帮助。

市面上有不少这样的库,比如args4j, jcommands等,我最后选用了args4j。

首先我们需要写一个类,里面用annotation来描述我们的程序需要什么样的参数:

public class Args {
    @Option(required=true, name="-aaa",usage="aaa is something")
    private String aaa;
    @Option(name="-bbb",usage="bbb is something")
    private String bbb;
    @Option(name="-ccc",usage="ccc is something")
    private String ccc;
    @Option(name="-ddd",usage="ddd is something")
    private String ddd;
    @Option(name="-eee",usage="eee is something")
    private String eee;
    @Option(name="-fff",usage="fff is something")
    private String fff;
    @Option(name="-ggg",usage="ggg is something")
    private String ggg;
 
    // getters for them
}

这样可以很清楚的方式知道每个参数的作用、描述等。

然后取值:

public static void main(String[] args) {
    Args myArgs = new Args();
    CmdLineParser parser = new CmdLineParser(myArgs);
    parser.parseArgument(myArgs);
}

这时,myArgs实例中的各fields,就已经自动赋予了相应的值,是由CmdLineParser通过反射赋值的。

想打印使用提示呢?

parser.printUsage(System.out);

它会根据Args里的定义,自动组织成一种可读性较好的格式,输出使用提示,十分贴心。

调用者:

java MyTool -aaa hello -bbb world1 -ccc world2 -ddd world3 -eee world4 -fff world5 -ggg world6 -hhh world7

虽然看起来调用方式跟之前没什么变化,但内涵却更加丰富了,而我们要做的,仅仅是定义一个描述类,和调用三两行代码而已。

这是我目前认为最优雅的解决方案。

向java的main()传入大量参数的更多相关文章

  1. clob字段的值插入和查询N种方法【包括java调用存储过程传入clob参数】

    import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import jav ...

  2. java程序main方法的参数String[] args

    public class ArgsTest { public static void main(String[] args) { System.out.println(args.length); fo ...

  3. 133、Java获取main主函数参数

    01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...

  4. java中方法传入参数时:值传递还是址传递?

    JAVA中的数据类型有两大类型: ① 基本数据类型:逻辑型(boolean).文本型(char).整数型(byte.short.int.long).浮点型(float.double) ② 引用数据类型 ...

  5. java项目打包成可运行的jar,main方法带参数

    转载 原文地址:http://www.cnblogs.com/neillee/p/6063808.html#commentform 将 java 项目打包成可运行的 jar 包(main 函数带参数) ...

  6. Java中eclipse与命令行向main函数传递参数

    我们知道main函数是java程序的入口,main函数的参数类型是String[]. 1.Eclipse中向main方法传递参数 例如: public class Mytest { public st ...

  7. cmd编译java程序出现:找不到或无法加载主类的原因以及解决办法 以及 给java的main方法传递args参数

    原因: 1.java源程序中没有主类main方法. 2.java源程序中包含有eclipse等IDE工具生成的package包. 解决办法(对应以上的原因): 1.运行含有main的类 2.将java ...

  8. 对于应用需要记录某个方法耗时的场景,必须使用clock_gettime传入CLOCK_MONOTONIC参数,该参数获得的是自系统开机起单调递增的纳秒级别精度时钟,相比gettimeofday精度提高不少,并且不受NTP等外部服务影响,能准确更准确来统计耗时(java中对应的是System.nanoTime),也就是说所有使用gettimeofday来统计耗时(java中是System.curre

    对于应用需要记录某个方法耗时的场景,必须使用clock_gettime传入CLOCK_MONOTONIC参数,该参数获得的是自系统开机起单调递增的纳秒级别精度时钟,相比gettimeofday精度提高 ...

  9. java之main

    Java中用户向系统传递参数的三种基本方式 main方法 在Java中,main()方法是Java应用程序的入口方法,也就是说,程序在运行的时候,第一个执行的方法就是main()方法,这个方法和其他的 ...

随机推荐

  1. UNIX环境高级编程笔记之进程控制

    本章重点介绍了进程控制的几个函数:fork.exec族._exit.wait和waitpid等,主要需要掌握的是父进程和子进程之间的运行机制,怎么处理进程的正常和异常终止.以及怎么让进程执行不同的程序 ...

  2. 配置<authorization>节(配置文件)

    在 Web.config 文件的<configuration>标记的子标记<authorization>和</authorization>之间用于设置应用程序的授权 ...

  3. MyBatis知多少(9)不同类型的数据库

    并非所有的数据库都如此复杂,需要使用昂贵的数据库管理系统以及企业级的硬件.一些数 据库其实非常小,足以运行在一台老式的PC机上.所有的数据库都是不一样的.它们有各自不 同的需求和不同的挑战.iBATI ...

  4. sizeof()用法汇总【转载】

    转载自:http://www.cnblogs.com/chengxin1982/archive/2009/01/13/1374575.html 参考:http://blog.csdn.net/free ...

  5. Vex – 超轻量!可以轻松自定义的现代风格弹窗插件

    Vex 的独特之处在于现代风格设计,能够自定义弹出模式.皮肤.Vex 超轻量,压缩后不到 2KB,提供了简洁的 API,可以根据自己的项目需要快速自定义.支持在移动设备上使用,测试通过的浏览器:IE8 ...

  6. TypeWonder – 在任何网站上实时预览字体效果

    TypeWonder 让网页字体的选择过程变得轻松愉快.它可以帮助您在任何网站上快速测试 Web 字体效果!输入网站网址,就能够即时预览的字体的实际效果,还可以从数百种字体中进行挑选,您还可以得到所需 ...

  7. 资料下载:敏捷个人的成长思考.pptx(第1次线下活动2011.04)

    本文挪至 http://www.zhoujingen.cn/blog/629.html PDF下载地址:http://down.51cto.com/data/207112 推荐:你可能需要的在线电子书 ...

  8. JS魔法堂:阻止元素被选中

    一.前言 在为IE5.5~9polyfill HTML5新特性placeholder时需要阻止元素被选中,因此在网上.书上查阅相关资料,记录在此以便日后查阅. 二.IE10+实现方式──CSS3 .u ...

  9. Vim杂记:Sublime的配色方案

    一.前言 爱美之心人皆有之,sublime的配色实在好看,于是希望Vim也能这样. 二.配置 1.下载monokai(https://github.com/sickill/vim-monokai),然 ...

  10. 团队项目SCRUM项目6.0 7.0

    6.0----------------------------------------------------- sprint演示 1.坚持所有的sprint都结束于演示. 团队的成果得到认可,会感觉 ...