use*_*382 256 java arrays backwards-compatibility variadic-functions
我希望能够创建一个像这样的函数:
class A {
private String extraVar;
public String myFormat(String format, Object ... args){
return String.format(format, extraVar, args);
}
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是在方法中args
处理,因此是单个参数,而我希望每个in 都作为新参数传递.既然也是一个带有变量参数的方法,这应该是可能的.Object[]
myFormat
String.format
Object
args
String.format
如果这是不可能的,有没有像这样的方法String.format(String format, Object[] args)
?在这种情况下,我可以在前面加上extraVar
到args
使用新的数组,并把它传递给该方法.
pol*_*nts 300
是的,a T...
只是a的语法糖T[]
.
列表中的最后一个正式参数是特殊的; 它可以是一个可变的arity参数,由类型后面的省略号表示.
如果最后一个形式参数是类型的变量arity参数
T
,则认为它定义了类型的形式参数T[]
.然后该方法是可变的arity方法.否则,它是一种固定的arity方法.变量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 ]"
}
Run Code Online (Sandbox Code Playgroud)
是的,上面的main
方法是有效的,因为再次,String...
只是String[]
.此外,因为数组是协变的,a String[]
是a Object[]
,所以你也可以调用ezFormat(args)
任何一种方式.
null
如何解决varargs是非常复杂的,有时它可能会让你感到惊讶.
考虑这个例子:
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!!!
Run Code Online (Sandbox Code Playgroud)
由于可变参数如何解决,最后的语句调用objs = null
,这当然会导致NullPointerException
用objs.length
.如果要为null
varargs参数提供一个参数,可以执行以下任一操作:
count(new Object[] { null }); // prints "1"
count((Object) null); // prints "1"
Run Code Online (Sandbox Code Playgroud)
以下是人们在处理varargs时提出的一些问题的示例:
正如您所知,以下内容并非"有效":
String[] myArgs = { "A", "B", "C" };
System.out.println(ezFormat(myArgs, "Z"));
// prints "[ [Ljava.lang.String;@13c5982 ][ Z ]"
Run Code Online (Sandbox Code Playgroud)
由于varargs的工作方式,ezFormat
实际上得到2个参数,第一个是a String[]
,第二个是a String
.如果你将一个数组传递给varargs,并且你希望它的元素被识别为单独的参数,并且你还需要添加一个额外的参数,那么你别无选择,只能创建另一个容纳额外元素的数组.
以下是一些有用的辅助方法:
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;
}
Run Code Online (Sandbox Code Playgroud)
现在您可以执行以下操作:
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 ]"
Run Code Online (Sandbox Code Playgroud)
它没有"工作":
int[] myNumbers = { 1, 2, 3 };
System.out.println(ezFormat(myNumbers));
// prints "[ [I@13c5982 ]"
Run Code Online (Sandbox Code Playgroud)
Varargs仅适用于引用类型.自动装箱不适用于基元数组.以下作品:
Integer[] myNumbers = { 1, 2, 3 };
System.out.println(ezFormat(myNumbers));
// prints "[ 1 ][ 2 ][ 3 ]"
Run Code Online (Sandbox Code Playgroud)
jas*_*p85 170
可变方法的基础类型function(Object... args)
是 function(Object[] args)
.Sun以这种方式添加了varargs以保持向后兼容性.
所以,你应该只能够预先考虑extraVar
到args
,并调用String.format(format, args)
.
mdm*_*dma 22
传递一个数组是可以的 - 实际上它也是一样的
String.format("%s %s", "hello", "world!");
Run Code Online (Sandbox Code Playgroud)
是相同的
String.format("%s %s", new Object[] { "hello", "world!"});
Run Code Online (Sandbox Code Playgroud)
这只是语法糖 - 编译器将第一个转换为第二个,因为底层方法期望vararg参数的数组.
看到
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);
Run Code Online (Sandbox Code Playgroud)
小智 5
我有同样的问题。
String[] arr= new String[] { "A", "B", "C" };
Object obj = arr;
Run Code Online (Sandbox Code Playgroud)
然后将 obj 作为 varargs 参数传递。有效。
归档时间: |
|
查看次数: |
195668 次 |
最近记录: |