首頁  >  文章  >  Java  >  解析Java的可變長參數清單及其使用時的注意點

解析Java的可變長參數清單及其使用時的注意點

高洛峰
高洛峰原創
2017-01-19 15:13:041480瀏覽

Java 可變參數列表

class A {}

由於所有的類別都繼承於Object,可以以Object數組為參數的方法:

public class parameter {
  static void printArray(Object[] args){
    for(Object obj : args){
      System.out.print(obj + " ");
    }
    System.out.println();
  }
   
  public static void main(String[] args){
    printArray(new Object[] {
        new Integer(47), new Float(3.14), new Double(11.11)
    });
    printArray(new Object[]{"one", "two", "there"});
    printArray(new Object[]{new A(), new A(), new A()});
  }
}

   

可以使用Object以為的參數列表:

public class parameter {
  public static void printArray(Object... args){
    for(Object obj : args){
      System.out.print(obj + " ");
    }
    System.out.println();
  }
   
  public static void main(String[] args){
    printArray(new Integer(47), new Float(3.14), new Double(11.11));
    printArray(47, 3.14F, 11.11);
    printArray("one", "two", "three");
    printArray(new A(), new A(), new A());
    printArray((Object[]) new Integer[]{1, 2, 3, 4});
    printArray();
  }
}

   

這是Java 5 引入的一個特性,如果一個方法要接收的參數數量是不確定的,那麼這個特性就可以派上用場了。

例如,在涉及IO操作的地方,基本上至少需要關閉兩個流:輸入、輸出,我喜歡把流關閉的操作封裝成下面的方法,這樣只需一次調用就可以關閉多個流。

public class VarargType{
  static void f(Character... args){
    System.out.print(args.getClass());
    System.out.println(" length " + args.length);
  }
   
  static void g(int... args){
    System.out.print(args.getClass());
    System.out.println(" length " + args.length);
  }
   
  public static void main(String[] args){
    f('a');
    f();
    g(1);
    g();
    System.out.println(" int [] " + new int[0].getClass());
  }
}

這是我覺得這個特性唯一適合使用的地方,具備下面的特點:

這些參數具有相同的類型;

參數數量不確定,每一個都是可選的;

這些參數的用途都是一樣的,例如上面都是執行關閉。

Java 可變長參數清單只能放在方法參數清單的最後。


Java可變長參數列表的實作

Java可變長參數列表的實作是透過編譯器把這些參數封裝成一個陣列來傳遞的。

例如上面的方法的簽章其實是: closeSilent(Closeable[] closeables) void 。

踩坑

有個方法,被A、B 兩個地方A、B 調用,9 月,在A 這裡需要增加一個參數,當時腦子一抽瘋,決定用可變長參數列表,覺得B 那裡不用改簡單點,坑就這樣埋下了。

最近要求 B 這裡要新增兩個參數,那就在方法的參數列表裡繼續加參數,這些參數的類型是不同的,所以可變長參數列表宣告成 Object 類型的。

第一個坑就是在這個方法內取可變長參數的元素時,沒考慮到有的參數是沒傳的,直接爆數組越位的異常了。馬上就覺得可變長參數列表的不好了,那就不用了唄,改為常規的固定形式的參數傳遞。

改完之後,在測試環境測了都沒問題。把生產環境的幾個類別替換之後,結果卻報錯了,方法找不到,一看方法簽名,還是陣列的,沒有替換到。從原始碼看,那個呼叫的地方不需要更改,所以沒想到要替換;由於測試環境是全量打包,所以不會有問題。

方法的簽名是在編譯的時候就確定了的,源碼層面看起來不需要改的不表示編譯後的類別也不需要替換了。

其實以前也聽過,在這種發包不規範的情況下,把源碼裡的一個常數值改了之後,只替換了這個定義常數的類文件,沒有把所有引用這個常數的類文件重新編譯替換,導致出現莫名其妙的問題。跟方法簽名的情況本質上是一樣的問題。

更多解析Java的可變長參數列表及其使用時的注意點相關文章請關注PHP中文網!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn