java - 我可以将数组作为参数传递给 Java 中具有可变参数的方法吗?

标签 java arrays backwards-compatibility variadic-functions

我希望能够创建如下函数:

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

这里的问题是 args 在方法 myFormat 中被视为 Object[],因此是 的单个参数>String.format,而我希望 args 中的每个 Object 都作为新参数传递。由于 String.format 也是一个带有可变参数的方法,这应该是可能的。

如果这不可能,有没有像 String.format(String format, Object[] args) 这样的方法?在这种情况下,我可以使用新数组将 extraVar 添加到 args 并将其传递给该方法。

最佳答案

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

JLS 8.4.1 Format parameters

The last formal parameter in a list is special; it may be a variable arity parameter, indicated by an elipsis following the type.

If the last formal parameter is a variable arity parameter of type T, it is considered to define a formal parameter of type T[]. The method is then a variable arity method. Otherwise, it is a fixed arity method. Invocations of a variable arity method may contain more actual argument expressions than formal parameters. All the actual argument expressions that do not correspond to the formal parameters preceding the variable arity parameter will be evaluated and the results stored into an array that will be passed to the method invocation.

这里有一个例子来说明:

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)

另见


可变参数陷阱 #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 = null,这当然会导致 NullPointerExceptionobjs.length .如果您想为可变参数提供一个 null 参数,您可以执行以下任一操作:

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

相关问题

以下是人们在处理可变参数时提出的一些问题示例:


可变参数陷阱 #2:添加额外参数

正如您所发现的,以下内容不起作用:

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

由于可变参数的工作方式,ezFormat 实际上有 2 个参数,第一个是 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 ]"

可变参数陷阱 #3:传递一个基元数组

它“不起作用”:

    int[] myNumbers = { 1, 2, 3 };
    System.out.println(ezFormat(myNumbers));
    // prints "[ [I@13c5982 ]"

可变参数仅适用于引用类型。自动装箱不适用于基元数组。以下作品:

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

关于java - 我可以将数组作为参数传递给 Java 中具有可变参数的方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2925153/

相关文章:

java - 相机预览 View ,水平,而应该是垂直 在 HTC Tattoo 上工作正常,在 Nexus 上坏了

java - PDF核心(Type1)字体下载?

java - Android ListFragment重叠

c - 移动字符串数组中的元素并用零填充

node.js - 在 “new Buffer(str)” 和 “Buffer.from(str)” 之间选择

Java - 我的 Action 事件不起作用

c - 初始化后分配给数组中的特定索引

ios - 字典不允许我将字符串附加到它的值

c# - 程序集兼容性问题

javascript - 隐藏来自半旧浏览器的脚本