项目中有一些用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传入参数_向java的main()传入大量参数相关推荐

  1. java项目----教务管理系统_基于Java的教务管理系统

    java项目----教务管理系统_基于Java的教务管理系统 2022-04-22 18:18·java基础 最近为客户开发了一套学校用教务管理系统,主要实现学生.课程.老师.选课等相关的信息化管理功 ...

  2. java请求参数_在Java中发送http的post请求,设置请求参数等等

    前几天做了一个定时导入数据的接口,需要发送http请求,第一次做这种的需求,特地记一下子, 导包 import java.text.SimpleDateFormat; import java.util ...

  3. java 反射 不定参数_关于 Java 中的 不定参数

    简单修改 JAVA中可以使用不定参数, 例如 public void test(String ...args){...} 这里test方法可以传入参数的情况是: 1.不使用参数,如test() 2.使 ...

  4. java 泛型参数_[基础]-Java泛型

    一.概述 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型. 泛型的本质是参数化类型,也就是说所操作的 ...

  5. java flowlayout参数_【Java布局】FlowLayout布局时设定组件大小

    默认的JPanel中,采用的是FlowLayout布局 下面是api中的定义: JPanel(boolean isDoubleBuffered) 创建具有 FlowLayout 和指定缓冲策略的新 J ...

  6. java 包装类可以被继承_【Java基本功】一文了解Java中继承、封装、多态的细节...

    本节主要介绍Java面向对象三大特性:继承 封装 多态,以及其中的原理. 本文会结合虚拟机对引用和对象的不同处理来介绍三大特性的原理. 继承 Java中的继承只能单继承,但是可以通过内部类继承其他类来 ...

  7. java 克隆的作用_关于java中克隆的学习(一)

    java中的克隆,就是要复制对象,但为什么要用克隆呢?我们直接把对象赋值给其它同类型的实例不就行了吗?这就要从java的值传递和引用传递说起了. package dcr.study.test.poin ...

  8. java是什么格式_是java格式

    错误:编码GBK的不可映射字符的解决办法 最近在重新补javaSE的基础,编辑器编写完代码以后,在控制台运行代码段的时候,出现了以下的错误提示:错误:编码GBK的不可映射字符 在通过查询谷哥和度娘以后 ...

  9. java数组子类型_[改善Java代码]数组的真实类型必须是泛型类型的子类型

    List接口的toArray方法可以把一个结合转化为数组,但是使用不方便,toArray()方法返回的是一个Object数组,所以需要自行转变. toArray(T[] a)虽然返回的是T类型的数组, ...

最新文章

  1. JavaScript模块化开发整理
  2. cdh 安装_使用Cloudera的CDH部署Hadoop:第三步,安装管理平台和数据库
  3. ASP.NET MVC中如何以ajax的方式在View和Action中传递数据
  4. boost::system::error_condition相关的测试程序
  5. Windows XP SP3?转自作者: 孤单的鸽子,  出处:天极yesky, 责任编辑: 袁绍龙
  6. 面试被吊打 - Redis原理
  7. ASP.NET Literal控件用法
  8. MySQL(7) ---删除数据库
  9. navicat导入成功但是没有数据_数据库能建立成功,但是还报错,应该怎么处理...
  10. Linux下testlink安装
  11. CGCS2000 VS WGS84
  12. Python多线程编程---(1)threading 模块 Thread 类
  13. 5、OC —— @property和@synthesize
  14. 【中医学】11 常见病证-2:心悸:眩晕:中风:血证:黄疸:痹证:消渴
  15. 深入浅出ASP .NET Core学习记录
  16. 透明度混合(Alpha blending)
  17. Flutter shared_preferences简单使用
  18. SpringBoot系列教程(六十七):SpringBoot自定义Fastjson为JSON消息转换器
  19. 在线生成免费android ios图标
  20. Android Killer中apktool插件更新

热门文章

  1. Python 进阶 —— defaultdict
  2. 构图之法——9条构图小贴士
  3. mysql图片数据类型_Mysql数据类型简介(大概了解)
  4. python 下载文件-python爬虫之下载文件的方式总结以及程序实例
  5. 零基础学python图文版-零基础学Minecraft编程(图文版) 中文pdf完整版[41MB]
  6. 学python能做什么-学Python后到底能干什么
  7. 人物 | 当我们在谈论语音识别时,我们在谈些什么?——知乎达人、CMU博士生王赟...
  8. 微信终于良心一回,更新了语音识别功能可识别粤语,广东人有福了
  9. HTML-图像,音频,视频和路径
  10. 能识别nvme的pe启动_【腾讯WeTest干货分享】机器学习在启动耗时测试中的应用及模型调优...