我希望能够创建如下函数:
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[]
的语法糖。
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
,这当然会导致 NullPointerException
和 objs.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 ]"
我是一名优秀的程序员,十分优秀!