qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請訪問 http://qaseven.github.io/

          Java中可變長參數(shù)的使用及注意事項

           在Java5 中提供了變長參數(shù)(varargs),也就是在方法定義中可以使用個數(shù)不確定的參數(shù),對于同一方法可以使用不同個數(shù)的參數(shù)調(diào)用,例如print("hello");print("hello","lisi");print("hello","張三", "alexia");下面介紹如何定義可變長參數(shù) 以及如何使用可變長參數(shù)。

            1. 可變長參數(shù)的定義

            使用...表示可變長參數(shù),例如

          print(String... args){
          ...
          }

            在具有可變長參數(shù)的方法中可以把參數(shù)當成數(shù)組使用,例如可以循環(huán)輸出所有的參數(shù)值。

          print(String... args){
             for(String temp:args)
                System.out.println(temp);
          }

            2. 可變長參數(shù)的方法的調(diào)用

            調(diào)用的時候可以給出任意多個參數(shù)也可不給參數(shù),例如:

          print();
          print("hello");
          print("hello","lisi");
          print("hello","張三", "alexia")

            3. 可變長參數(shù)的使用規(guī)則

            3.1 在調(diào)用方法的時候,如果能夠和固定參數(shù)的方法匹配,也能夠與可變長參數(shù)的方法匹配,則選擇固定參數(shù)的方法。看下面代碼的輸出:

          package com;
          // 這里使用了靜態(tài)導入
          import static java.lang.System.out;
          public class VarArgsTest {
          public void print(String... args) {
          for (int i = 0; i < args.length; i++) {
          out.println(args[i]);
          }
          }
          public void print(String test) {
          out.println("----------");
          }
          public static void main(String[] args) {
          VarArgsTest test = new VarArgsTest();
          test.print("hello");
          test.print("hello", "alexia");
          }
          }



            3.2 如果要調(diào)用的方法可以和兩個可變參數(shù)匹配,則出現(xiàn)錯誤,例如下面的代碼:

          package com;
          // 這里使用了靜態(tài)導入
          import static java.lang.System.out;
          public class VarArgsTest1 {
          public void print(String... args) {
          for (int i = 0; i < args.length; i++) {
          out.println(args[i]);
          }
          }
          public void print(String test,String...args ){
          out.println("----------");
          }
          public static void main(String[] args) {
          VarArgsTest1 test = new VarArgsTest1();
          test.print("hello");
          test.print("hello", "alexia");
          }
          }

              對于上面的代碼,main方法中的兩個調(diào)用都不能編譯通過,因為編譯器不知道該選哪個方法調(diào)用,如下所示:

            3.3 一個方法只能有一個可變長參數(shù),并且這個可變長參數(shù)必須是該方法的最后一個參數(shù)

            以下兩種方法定義都是錯誤的。

          public void test(String... strings,ArrayList list){
          }
          public void test(String... strings,ArrayList... list){
          }

            4. 可變長參數(shù)的使用規(guī)范

            4.1 避免帶有可變長參數(shù)的方法重載:如3.1中,編譯器雖然知道怎么調(diào)用,但人容易陷入調(diào)用的陷阱及誤區(qū)

            4.2 別讓null值和空值威脅到變長方法,如3.2中所示,為了說明null值的調(diào)用,重新給出一個例子:

          package com;public class VarArgsTest1 {
          public void print(String test, Integer... is) {
          }
          public void print(String test,String...args ){
          }
          public static void main(String[] args) {
          VarArgsTest1 test = new VarArgsTest1();
          test.print("hello");
          test.print("hello", null);
          }
          }

             這時會發(fā)現(xiàn)兩個調(diào)用編譯都不通過:





           因為兩個方法都匹配,編譯器不知道選哪個,于是報錯了,這里同時還有個非常不好的編碼習慣,即調(diào)用者隱藏了實參類型,這是非常危險的,不僅僅調(diào)用者需要“猜測”該調(diào)用哪個方法,而且被調(diào)用者也可能產(chǎn)生內(nèi)部邏輯混亂的情況。對于本例來說應該做如下修改:

            因為兩個方法都匹配,編譯器不知道選哪個,于是報錯了,這里同時還有個非常不好的編碼習慣,即調(diào)用者隱藏了實參類型,這是非常危險的,不僅僅調(diào)用者需要“猜測”該調(diào)用哪個方法,而且被調(diào)用者也可能產(chǎn)生內(nèi)部邏輯混亂的情況。對于本例來說應該做如下修改:

              4.3 覆寫變長方法也要循規(guī)蹈矩

            下面看一個例子,大家猜測下程序能不能編譯通過:

          package com;
          public class VarArgsTest2 {
          /**
          * @param args
          */
          public static void main(String[] args) {
          // TODO Auto-generated method stub
          // 向上轉(zhuǎn)型
          Base base = new Sub();
          base.print("hello");
          // 不轉(zhuǎn)型
          Sub sub = new Sub();
          sub.print("hello");
          }
          }
          // 基類
          class Base {
          void print(String... args) {
          System.out.println("Base......test");
          }
          }
          // 子類,覆寫父類方法
          class Sub extends Base {
          @Override
          void print(String[] args) {
          System.out.println("Sub......test");
          }
          }

              答案當然是編譯不通過,是不是覺得很奇怪?

            第一個能編譯通過,這是為什么呢?事實上,base對象把子類對象sub做了向上轉(zhuǎn)型,形參列表是由父類決定的,當然能通過。而看看子類直接調(diào)用的情況,這時編譯器看到子類覆寫了父類的print方法,因此肯定使用子類重新定義的print方法,盡管參數(shù)列表不匹配也不會跑到父類再去匹配下,因為找到了就不再找了,因此有了類型不匹配的錯誤。

            這是個特例,覆寫的方法參數(shù)列表竟然可以與父類不相同,這違背了覆寫的定義,并且會引發(fā)莫名其妙的錯誤。

            這里,總結(jié)下覆寫必須滿足的條件:

            (1)重寫方法不能縮小訪問權(quán)限;

            (2)參數(shù)列表必須與被重寫方法相同(包括顯示形式);

            (3)返回類型必須與被重寫方法的相同或是其子類;

            (4)重寫方法不能拋出新的異常,或者超過了父類范圍的異常,但是可以拋出更少、更有限的異常,或者不拋出異常。

           最后,給出一個有陷阱的例子,大家應該知道輸出結(jié)果:

          package com;
          public class VarArgsTest {
          public static void m1(String s, String... ss) {
          for (int i = 0; i < ss.length; i++) {
          System.out.println(ss[i]);
          }
          }
          public static void main(String[] args) {
          m1("");
          m1("aaa");
          m1("aaa", "bbb");
          }
          }

          posted on 2013-07-26 10:20 順其自然EVO 閱讀(1160) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導航:
           
          <2013年7月>
          30123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          導航

          統(tǒng)計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 九龙县| 广东省| 永登县| 保靖县| 漳平市| 盐边县| 北安市| 剑河县| 滦平县| 庆元县| 喜德县| 普格县| 民勤县| 崇信县| 长宁县| 监利县| 武陟县| 郯城县| 兰溪市| 金秀| 开江县| 牙克石市| 连山| 靖西县| 海门市| 永平县| 平和县| 洛扎县| 鄂尔多斯市| 津南区| 商丘市| 工布江达县| 云阳县| 商都县| 双桥区| 深水埗区| 邢台市| 昔阳县| 五常市| 黎城县| 清流县|