试图仅使用来自java.util.function
的预定义功能接口,我开始想知道为什么不能在类型声明中指定varargs。例如,我想提供可以像这样使用的API
object.method((x, y, z) -> x + y - z)
method
取n个参数的数学函数。以下是我希望object
界面看起来像
interface I {
I method(ToDoubleFunction<double...> f);
}
我确实知道我可以定义自己的功能界面,或者在尖括号内略微指定double[]
更改API。我很好奇为什么上面提到这样做是不可行的。
修改
在评论中有一个解释为什么上面的例子不正确使用varargs。 Radiodef将我的问题分成两个分开的
- 为什么不允许vararg作为通用参数和
- 为什么你不能在Java中按名称声明和访问vararg。
醇>
由于问题的标题,我必须坚持第一个问题。这是预期的行为:
ToDoubleFunction<double...> lambda = (double... d) -> d[0] + d[1] - d[2];
lambda.applyAsDouble(1, 2, 3);
答案 0 :(得分:3)
将方法参数声明为varargs意味着调用者可以提供任意数量的参数,接收器将像数组一样处理这些参数。
因此,无论你是否写下来,它都没有区别:
static double f(double... a) { return a[0]+a[1]-a[2]; }
或
static double f(double[] a) { return a[0]+a[1]-a[2]; }
因此,为了写下一个实现函数的lambda表达式,将参数指定为varargs是无关紧要的,特别是因为你可以省略参数类型所以没有人看到{{1}或隐含[]
。
因此,当您拒绝使用自己的界面时,您必须写下
...
当然,请记住,您的代码假设某个数组长度。
使用辅助界面,事情可能会更容易:
ToDoubleFunction<double[]> f=a->a[0]+a[1]-a[2];
然后你可以写:
interface F3 extends ToDoubleFunction<double[]> {
double apply(double a0, double a1, double a2);
default double applyAsDouble(double[] a) {
return apply(a[0], a[1], a[2]);
}
}
类似的东西适用于等效的ToDoubleFunction<double[]> f=(F3)(x,y,z)->x+y-z;
接口等,你可以将它们全部处理为F4
但编译器不会在混合使用不同的数组假设的代码时发出警告长度(当你假设一个不太可变的arity时,与varargs的问题相同)。
调用一个数组,期望不将参数声明为vararg的方法总是可以用 期望varargs的辅助方法包装:
ToDoubleFunction<double[]>
使用这种方法,您可以将您的函数评估为static double apply(ToDoubleFunction<double[]> f, double... arg) {
return f.applyAsDouble(arg);
}
我是否提到当参数数量不匹配时编译器不会发出警告?