有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

vararg内部类型声明的java规范

为了只利用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. why vararg is not allowed as a generic argument and
  2. why you cannot declare and access vararg by name in Java.

由于问题的标题,我不得不坚持第一个问题。以下是预期的行为:

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

共 (1) 个答案

  1. # 1 楼答案

    将方法参数声明为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是无关紧要的,特别是当您可以省略参数类型时,这样就没有人会看到[]...是隐含的

    因此,当您拒绝使用自己的界面时,您将不得不写下

    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时,与varargs的问题相同)

    调用未将参数声明为vararg的数组预期方法时,始终可以使用辅助方法进行包装,该辅助方法预期varargs:

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

    使用这种方法,您可以像apply(f, 1, 2, 3)一样简单地计算函数

    我有没有提到编译器不会在参数数量不匹配时警告您