2014-11-05 37 views
2

为了只使用来自java.util.function的预定义函数接口,我开始想知道为什么不能在类型声明中指定可变参数。例如,我想提供的API,它可以像这样可变内部类型声明的规范

object.method((x, y, z) -> x + y - z) 

method需要的n个参数数学函数来使用。以下是我希望我的object界面看起来像

interface I { 
    I method(ToDoubleFunction<double...> f); 
} 

我不知道我可以定义自己的funcional接口,或更改API略指定double[]尖括号。我很好奇,为什么上面提到的做法是不可行的。

编辑:

在评论中有一个解释,为什么上面的例子不是可变参数的正确用法。 Radiodef分我quesion成两个分开的人

  1. 为什么可变参数不允许作为一个一般的参数和
  2. 为什么你不能在Java中的名字声明和访问可变参数。

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

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

您可以给出一个有用的例子,说明'方法'在这种情况下会做什么,不知道函数的arity是否仍然会导致有用的操作? – 2014-11-05 18:41:27

+0

Java可变参数不能以这种方式工作'(x,y,z) - > x + y - z'。参数作为一个数组传递,所以你想要做的是按名称访问数组索引,可变参数可以使用任意数量的索引来获取数组。 – Radiodef 2014-11-05 18:45:10

+2

也许值得注意的是,我不认为你真正想要的是变量arity,而是对n元组的隐式支持。元组更有用,因为元组仍然是内置的类型。不幸的是,Java不支持元组。 – 2014-11-05 18:55:52

回答

3

声明的方法参数作为可变参数意味着呼叫者可以提供的参数其中接收机将处理像阵列的任意数量。

因此,它是为实现您是否写没有区别:

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表达式,这实现的功能,这是无关紧要是否一个参数被指定为可变参数,特别是因为您可以省略参数类型,因此没有人会看到是否隐含[]...

所以,当你拒绝使用自己的界面,你将不得不写下来

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接口等工作,并且你可以将它们全部处理为ToDoubleFunction<double[]>,但当你将代码与数组长度不同的假设混合在一起时,编译器不会警告你(当你假设一个不太可变的arity时,与可变参数相同的问题)。

调用数组期待不声明参数作为变量参数可以随时与确实想到一个辅助方法包裹方法可变参数:

static double apply(ToDoubleFunction<double[]> f, double... arg) { 
    return f.applyAsDouble(arg); 
} 

你可以评估你的功能这样的方法简单如apply(f, 1, 2, 3)

我有没有提到编译器不会在参数个数不匹配时发出警告?