繁体   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
}

主.java

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
}

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

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可以读到:

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

话虽这么说,你可以做的是:

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

Output:

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

this answer所示,您可以通过处理可变参数参数的 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();
    }
}

然后,非关联操作可以通过处理所有 arguments 的 lambda 表达式来实现Calculator<T> ,而关联操作可以像这样实现:

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

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

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