向java的main()傳入大量參數

來源:互聯網
上載者:User

標籤:

項目中有一些用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()傳入大量參數

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.