vararg内部类型声明的规范

时间:2014-11-05 18:35:57

标签: java generics java-8

试图仅使用来自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将我的问题分成两个分开的

  
      
  1. 为什么不允许vararg作为通用参数和
  2.   
  3. 为什么你不能在Java中按名称声明和访问vararg。
  4.   

由于问题的标题,我必须坚持第一个问题。这是预期的行为:

 ToDoubleFunction<double...> lambda = (double... d) -> d[0] + d[1] - d[2];
 lambda.applyAsDouble(1, 2, 3);

1 个答案:

答案 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); }

这么简单

我是否提到当参数数量不匹配时编译器不会发出警告?

相关问题