我可以將數組作為參數傳遞給Java中具有可變參數的方法嗎?




arrays backwards-compatibility (4)

我希望能夠創建一個功能,如:

class A {
  private String extraVar;
  public String myFormat(String format, Object ... args){
    return String.format(format, extraVar, args);
  }
}

這裡的問題是argsmyFormat方法中被當作Object[]處理,因此是String.format的單個參數,而我希望args每個Object都作為新參數傳遞。 由於String.format也是一個可變參數的方法,所以這應該是可能的。

如果這是不可能的,有沒有像String.format(String format, Object[] args) ? 在這種情況下,我可以使用一個新的數組將extraVar預先extraVarargs ,並將其傳遞給該方法。

https://code.i-harness.com


jasonmp85是正確的關於傳遞一個不同的數組到String.format 。 數組的大小一旦構建就無法更改,因此您必須傳遞一個新數組而不是修改現有數組。

Object newArgs = new Object[args.length+1];
System.arraycopy(args, 0, newArgs, 1, args.length);
newArgs[0] = extraVar; 
String.format(format, extraVar, args);

傳遞一個數組是可以的 - 事實上它也是一樣的

String.format("%s %s", "hello", "world!");

是相同的

String.format("%s %s", new Object[] { "hello", "world!"});

它只是語法糖 - 編譯器會將第一個轉換為第二個,因為基礎方法期望為vararg參數提供一個數組。

看到


我有同樣的問題。

String[] arr= new String[] { "A", "B", "C" };
Object obj = arr;

然後通過obj作為可變參數。 有效。


是的, T...只是T[]的語法糖。

JLS 8.4.1格式參數

列表中的最後一個形式參數是特殊的; 它可能是一個變量arity參數,由類型後面的elipsis表示。

如果最後的形式參數是類型T的變量arity參數,則認為它定義了類型T[]的形式參數。 該方法是一個可變的方法。 否則,它是一種固定的方法。 變量arity方法的調用可能包含比形式參數更多的實際參數表達式。 所有與變量arity參數前面的形式參數不相對應的實際參數表達式將被計算,並將結果存儲到將傳遞給方法調用的數組中。

這裡有一個例子來說明:

public static String ezFormat(Object... args) {
    String format = new String(new char[args.length])
        .replace("\0", "[ %s ]");
    return String.format(format, args);
}
public static void main(String... args) {
    System.out.println(ezFormat("A", "B", "C"));
    // prints "[ A ][ B ][ C ]"
}

是的,上面的main方法是有效的,因為再次, String...只是String[] 。 另外,因為數組是協變的,所以String[]是一個Object[] ,所以你也可以以任何方式調用ezFormat(args)

也可以看看

Varargs陷阱#1:通過null

可變參數如何解決是相當複雜的,有時它會做出讓您感到驚訝的事情。

考慮這個例子:

static void count(Object... objs) {
    System.out.println(objs.length);
}

count(null, null, null); // prints "3"
count(null, null); // prints "2"
count(null); // throws java.lang.NullPointerException!!!

由於varargs的解析方式,最後一條語句調用objs.length objs = null ,這當然會導致帶有objs.length NullPointerException 。 如果你想給一個varargs參數一個null參數,你可以執行以下任一操作:

count(new Object[] { null }); // prints "1"
count((Object) null); // prints "1"

相關問題

以下是人們在處理可變參數時詢問的一些問題的示例:

Vararg陷阱#2:增加額外的論據

正如你發現的那樣,下面的內容不會“起作用”:

    String[] myArgs = { "A", "B", "C" };
    System.out.println(ezFormat(myArgs, "Z"));
    // prints "[ [Ljava.lang.String;@13c5982 ][ Z ]"

由於varargs的工作方式, ezFormat實際上有兩個參數,第一個是String[] ,第二個是String 。 如果您將數組傳遞給可變參數,並且您希望將其元素識別為單個參數,並且還需要添加額外參數,那麼您別無選擇,只能創建另一個容納額外元素的數組

以下是一些有用的幫手方法:

static <T> T[] append(T[] arr, T lastElement) {
    final int N = arr.length;
    arr = java.util.Arrays.copyOf(arr, N+1);
    arr[N] = lastElement;
    return arr;
}
static <T> T[] prepend(T[] arr, T firstElement) {
    final int N = arr.length;
    arr = java.util.Arrays.copyOf(arr, N+1);
    System.arraycopy(arr, 0, arr, 1, N);
    arr[0] = firstElement;
    return arr;
}

現在您可以執行以下操作:

    String[] myArgs = { "A", "B", "C" };
    System.out.println(ezFormat(append(myArgs, "Z")));
    // prints "[ A ][ B ][ C ][ Z ]"

    System.out.println(ezFormat(prepend(myArgs, "Z")));
    // prints "[ Z ][ A ][ B ][ C ]"

Varargs陷阱#3:傳遞一系列基元

它不“工作”:

    int[] myNumbers = { 1, 2, 3 };
    System.out.println(ezFormat(myNumbers));
    // prints "[ [[email protected] ]"

可變參數只適用於參考類型。 自動裝箱不適用於基元數組。 以下工作:

    Integer[] myNumbers = { 1, 2, 3 };
    System.out.println(ezFormat(myNumbers));
    // prints "[ 1 ][ 2 ][ 3 ]"




variadic-functions