向java的main()传入大量参数
项目中有一些用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
方案,要稍好一些。
只能做到这个程度了吗?看上面的三种方案,实际上都存在着一些问题,需要写更多代码:
- 打印usage
- 对参数进行检查,如果有缺少的或不合理的,要提示错误
这些缺失的工作实际上相当烦琐,让我们的代码更加混乱,却又不可或缺。
有没有优雅一些的方式呢?答案是有,我们可以利用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()传入大量参数的更多相关文章
- clob字段的值插入和查询N种方法【包括java调用存储过程传入clob参数】
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import jav ...
- java程序main方法的参数String[] args
public class ArgsTest { public static void main(String[] args) { System.out.println(args.length); fo ...
- 133、Java获取main主函数参数
01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...
- java中方法传入参数时:值传递还是址传递?
JAVA中的数据类型有两大类型: ① 基本数据类型:逻辑型(boolean).文本型(char).整数型(byte.short.int.long).浮点型(float.double) ② 引用数据类型 ...
- java项目打包成可运行的jar,main方法带参数
转载 原文地址:http://www.cnblogs.com/neillee/p/6063808.html#commentform 将 java 项目打包成可运行的 jar 包(main 函数带参数) ...
- Java中eclipse与命令行向main函数传递参数
我们知道main函数是java程序的入口,main函数的参数类型是String[]. 1.Eclipse中向main方法传递参数 例如: public class Mytest { public st ...
- cmd编译java程序出现:找不到或无法加载主类的原因以及解决办法 以及 给java的main方法传递args参数
原因: 1.java源程序中没有主类main方法. 2.java源程序中包含有eclipse等IDE工具生成的package包. 解决办法(对应以上的原因): 1.运行含有main的类 2.将java ...
- 对于应用需要记录某个方法耗时的场景,必须使用clock_gettime传入CLOCK_MONOTONIC参数,该参数获得的是自系统开机起单调递增的纳秒级别精度时钟,相比gettimeofday精度提高不少,并且不受NTP等外部服务影响,能准确更准确来统计耗时(java中对应的是System.nanoTime),也就是说所有使用gettimeofday来统计耗时(java中是System.curre
对于应用需要记录某个方法耗时的场景,必须使用clock_gettime传入CLOCK_MONOTONIC参数,该参数获得的是自系统开机起单调递增的纳秒级别精度时钟,相比gettimeofday精度提高 ...
- java之main
Java中用户向系统传递参数的三种基本方式 main方法 在Java中,main()方法是Java应用程序的入口方法,也就是说,程序在运行的时候,第一个执行的方法就是main()方法,这个方法和其他的 ...
随机推荐
- truncate/drop表非常慢,怎么办?用硬链接,极速体验
这个这个,我必须花巨大篇幅,记录下今天清空表记录的英雄壮举,可知道一个drop操作,执行了一下午啊一下午,这是要急出翔的节奏..呵呵,下面开始 我的需求:某表因历史原因,积压了1亿条记录,约占360G ...
- Android Studio 简单功能介绍
Android Studio 建立系统工具包你用来生成,测试,运行您的应用程序和软件包.构建系统是独立于Android的工作室,所以你可以调用它的Android的工作室或从命令行.在你写你的应用程序 ...
- ios面试技术要点
iOS面试 技术总结点(可参考):多线程 运行时 runloop app框架 几种动画编程 jsonmodel原理 sdwebimage原理 masonry怎么应用及原理 应用框架有哪些 说一下Fac ...
- ops中set_sysclk set_clkdiv set_pll详解
在看Alsa soc驱动的是时候,在snd_soc_dai_driver.ops中有3个字段 .set_sysclk .set_pll .set_clkdiv 开始的时候,总是晕头转向,感觉这3个回调 ...
- VPN有什么用?(转载)
VPN有什么用?转载自:http://www.chinaz.com/web/2012/0320/240819.shtml 当你非常非常想访问一个国外的网站,而这个网站被防火墙屏蔽的时候,你应该怎么做呢 ...
- js转html实体
方法一: 用的浏览器内部转换器实现转换,方法是动态创建一个容器标签元素,如DIV,将要转换的字符串设置为这个元素的innerText,然后返回这个元素的innerHTML,即得到经过HTML编码转换的 ...
- iOS 7.1 安装 企业应用 提示 无法下载应用程序
首先这种情况排除https影响,这个就不提了.请自行查询iOS https 部署. 其次系统版本是iOS 7.1,之后的版本安装都没问题. 说下我是怎么发现问题的,我找了个真机,发现直接调试提示bun ...
- vs2010安装和使用
vs2010是之前我跟老师做网站项目时安装的,这次软件工程作业我就用它了,安装过程中的截图就不存在了,我就详细说说它的使用吧. VS2010软件挺大的,下载大概要一个多小时,安装过程大概都是下一步. ...
- SQL查询语句去除重复行
1.存在两条完全相同的纪录 这是最简单的一种情况,用关键字distinct就可以去掉 select distinct * from table(表名) where (条件) 2.存在部分字段相同的纪录 ...
- 分析SIX锁和锁分区导致的死锁
什么是SIX锁? 官方文档锁模式中说到: 意向排他共享 (SIX):保护针对层次结构中某些(而并非所有)低层资源请求或获取的共享锁以及针对某些(而并非所有)低层资源请求或获取的意向排他锁. 顶级资源允 ...