我可以将一个数组作为parameter passing给Java中具有可变参数的方法吗?
我想能够创build一个function,如:
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
都作为新的parameter passing。 由于String.format
也是一个可变参数的方法,这应该是可能的。
如果这是不可能的,是否有像String.format(String format, Object[] args)
? 在这种情况下,我可以prepend extraVar
使用一个新的数组args
并传递给该方法。
可变参数方法function(Object... args)
的基础types是 function(Object[] args)
。 Sun以这种方式增加了可变参数,以保持向后兼容性。
所以你应该能够预先extraVar
args
和调用String.format(format, args)
。
是的,一个T...
只是一个T[]
的语法糖。
JLS 8.4.1格式参数
列表中的最后一个forms参数是特殊的; 它可能是一个可变的参数参数,由types后面的省略号表示。
如果最后一个forms参数是types
T
的variablesarity参数,则认为它定义了typesT[]
的forms参数。 该方法是一个可变的方法。 否则,这是一个固定的方法。 variablesarity方法的调用可能包含比forms参数更多的实际参数expression式。 所有与variablesarity参数前面的forms参数不相对应的实际参数expression式将被计算,并将结果存储到将传递给方法调用的数组中。
下面是一个例子来说明:
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)
。
也可以看看
- Java语言指南/可变参数
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!!!
由于如何解决可变参数,最后一个语句调用objs.length
objs = null
,这当然会导致与objs.length
NullPointerException
。 如果你想给一个variables参数一个null
参数,你可以执行以下任一操作:
count(new Object[] { null }); // prints "1" count((Object) null); // prints "1"
相关问题
以下是人们在处理可变参数时询问的一些问题的示例:
- 错误与可变参数和重载?
- 如何使用可变参数和reflection
- 最具体的方法与固定/可变参数匹配(可变参数)
Vararg陷阱#2:增加额外的论据
正如你发现的那样,下面的内容不会“起作用”:
String[] myArgs = { "A", "B", "C" }; System.out.println(ezFormat(myArgs, "Z")); // prints "[ [Ljava.lang.String;@13c5982 ][ Z ]"
由于varargs的工作方式, ezFormat
实际上有两个参数,第一个是String[]
,第二个是String
。 如果将数组传递给可变参数,并且希望将其元素识别为单独的参数,并且还需要添加一个额外的参数,那么您别无select,只能创build另一个容纳额外元素的数组 。
这里有一些有用的帮手方法:
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 "[ [I@13c5982 ]"
可变参数只适用于参考types。 自动装箱不适用于原始数组。 以下工作:
Integer[] myNumbers = { 1, 2, 3 }; System.out.println(ezFormat(myNumbers)); // prints "[ 1 ][ 2 ][ 3 ]"
传递一个数组是可以的 – 事实上它是相同的
String.format("%s %s", "hello", "world!");
是相同的
String.format("%s %s", new Object[] { "hello", "world!"});
它只是语法糖 – 编译器将第一个转换为第二个,因为基础方法期望vararg参数的数组。
看到
- 可变参数 – J2SE 1.5文档
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);