繁体   English   中英

是否可以使用可选参数制作通用功能接口?

Is it possible to make a generic functional interface with optional parameter(s)?

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我正在尝试使用单个方法(当然)在 Java 中创建一个功能接口,该方法可以采用任何类型的参数并返回任何数据类型(泛型方法)。

这是我到目前为止:

计算器.java

public interface Calculator<T> {
    T operation(T n1, T... n2); //this is where the optional parameter comes in
}

主程序

public static void main(String[] args) {
    Calculator<Integer> addition = (n1, n2) -> n1 + n2; //this gives an error
}

错误说:

二元运算符“+”的错误操作数类型

  • 是否可以在 Java 中创建带有可选参数的通用功能接口?
  • 如果是这样,我做错了什么?
2 个回复
public interface Calculator<T> {
    T operation(T n1, T .. n2); //this is where the optional parameter comes in
}

错误来自您尝试将运算符+应用于整数和整数数组的事实。 例如以下

public interface Calculator<T> {
    T operation(T n1, T n2); //this is where the optional parameter comes in
}

会正常工作,因为您会将运算符+应用于两个整数。

如果要保持相同的接口,则需要将主代码更改为:

public static void main(String[] args) {
    Calculator<Integer> addition = (n1, n2) -> n1 + Arrays.stream(n2).reduce(0, Integer::sum);
}

是否可以在 Java 中创建带有可选参数的通用功能接口?

从这个SO Thread可以读到:

varargs 可以做到这一点(在某种程度上)。 除此之外,必须提供方法声明中的所有变量。 如果您希望变量是可选的,您可以使用不需要参数的签名来重载该方法。

话虽如此,你可以做的是:

public interface Calculator<T> {
    T operation(T ...n);
}

这样,方法operation可以接受 0, 1 ... N 个元素甚至null

然后在你的主要:

Calculator<Integer> addition = n -> (n == null) ? 0 : 
                                    Arrays.stream(n).reduce(0, Integer::sum);

一个正在运行的例子:

public class Main {
    public static void main(String[] args) {
        Calculator<Integer> addition = n -> (n == null) ? 0 : Arrays.stream(n).reduce(0, Integer::sum);
        System.out.println(addition.operation(1, 2));
        System.out.println(addition.operation(1));
        System.out.println(addition.operation());
        System.out.println(addition.operation(null));
    }
}

输出:

3 // 1 + 2
1 // 1
0 // empty array 
0 // null

本答案所示,您可以通过 lambda 表达式处理可变参数参数来实现您的接口,例如使用 Stream。 但是您也可以为关联操作设计一个接口,除了提供两个参数版本之外,还提供默认方法:

interface Calculator<T> {
    T operation(T n1, T n2);
    default T operation(T first, T... args) {
        return Stream.concat(Stream.of(first), Arrays.stream(args))
            .reduce(this::operation).orElseThrow();
    }
}

请注意,方法签名operation(T first, T... args)强制要求至少有一个元素,这允许使用reduce而不使用标识元素或空流的回退值。

你可以像这样使用它

Calculator<Integer> addition = (n1, n2) -> n1 + n2;
Integer sum = addition.operation(1, 2, 3, 4);

但是操作必须是关联的,如加法、乘法或字符串连接等。如果您想支持非关联操作,这些操作必须使用适当的实现覆盖operation(T first, T... args) 覆盖它不适用于 lambda 表达式。 另一种方法是拥有一个用于任意计算的接口和一个用于关联操作的专业化:

interface Calculator<T> {
    T operation(T first, T... args);
}
interface AssociativeOp<T> extends Calculator<T> {
    T operation(T n1, T n2);
    @Override
    default T operation(T first, T... args) {
        return Stream.concat(Stream.of(first), Arrays.stream(args))
            .reduce(this::operation).orElseThrow();
    }
}

然后,非关联操作可以通过处理所有参数的 lambda 表达式实现Calculator<T>而关联操作可以实现如下:

Calculator<Integer> addition = (AssociativeOp<Integer>)(n1, n2) -> n1 + n2;

工厂方法可以消除类型转换的必要性,对其参数使用类型推断。 然而,当我们在这一点上时,我们可以记住,已经有一个函数式接口类型,用于带有两个参数的操作,示例甚至隐式使用了这些参数。 所以另一种选择是:

interface Calculator<T> {
    T operation(T first, T... args);

    static <U> Calculator<U> associative(BinaryOperator<U> op) {
        return (first,other) -> Stream.concat(Stream.of(first), Arrays.stream(other))
            .reduce(op).orElseThrow();
    }
}

这仍然允许通过 lambda 表达式进行任意实现,而关联操作可以通过简化来实现:

Calculator<Integer> addition = Calculator.associative((n1, n2) -> n1 + n2);

(或Calculator.associative(Integer::sum)

1 通用功能接口

我面临一些lambda问题。 我正在尝试使用lambda表达式和函数接口来创建接受函数接口和一些参数并执行该函数的方法。 这是我的代码: } 我有错误: 对于SomeClass类型,方法runLongAction((arg1,arg2) - &gt; {},Ar ...

3 通用功能作为功能接口?

我有以下函数,该函数返回与传递的List类型相同的List 。 除了Java Functional Interface的形式之外,我希望具有相同的功能。 我尝试了以下方法: 但是它不喜欢&lt;T&gt; 。 如果我像这样省略&lt;T&gt; : 它声称找不到类型T ...

4 通用功能接口使用使用者的简单示例

我正在尝试编写一个接受功能接口的通用方法。 参见示例。 任何帮助表示赞赏。 更新:使其编译并运行。 对改进或澄清的意见或建议感兴趣。 我将不会创建类型化抽象基类。 将一个附加参数添加到repeat方法中,指定在哪个机器人上执行命令,这与其他类似示例更加一致。 思考? ...

5 使用功能接口抽象通用代码的问题

在这里,我实现了以下两个功能,如下所示: 以上两个函数在不同的流程中被调用。 从上面的两个函数中,我想通过编写如下另一个函数来抽象出acquireLock和releaseLock功能: 我无法弄清楚如何实现executeWithLock函数,在这种情况下,我已经阅读了sta ...

6 通用功能接口和类型擦除

以下编译错误是什么意思? FooSetter类型的方法apply(Sample.Foo,capture#5-of?)不适用于参数(Sample.Foo,capture#6-of?) 它发生在下面的代码中(在我用注释指示的底部),该代码尝试将一个bean的setter映射到另一个bea ...

10 如何相互使用功能接口

首先,对不起我的英语,因为它不好,但是我在功能接口方面有问题... 我有Hello类,主要方法: 在那之后: Make是Execute类中的方法。 在这种方法中,我应该运行功能选项卡。 例如:functionB是根据functionA的结果来构造自己的身体,函数C是根据 ...

2016-10-29 15:40:01 0 34   java
暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM