【问题标题】:Java 8 Lambda expression - Method overloading doubtsJava 8 Lambda 表达式——方法重载的疑惑
【发布时间】:2017-05-27 21:32:41
【问题描述】:

我正在努力学习 Lambda 表达式,

interface MathOperartor 为 int 和 float 类型重载了 operation(),我确信使用 Lambda 表达式应该可以做到这一点,但似乎无法弄清楚这里的问题是什么:

public static void main(String[] args) {
    LambdaLearning lb = new LambdaLearning();

    MathOperartor add = (a , b )->  a + b;  // error: The target type of this expression must be a functional interface
    MathOperartor sub = (a , b) -> a - b;   // same error
    MathOperartor mul = (a , b) -> a * b;   //  ''
    MathOperartor div = (a , b) -> a / b;   //  ''

    System.out.println(lb.operate(10, 15, add));
    System.out.println(lb.operate(10.5f, 15.5f, sub));
    System.out.println(lb.operate(10, 15, mul));
    System.out.println(lb.operate(10, 15, div));

}

interface MathOperartor{
    public Object operate(int a, int b);
    public Object operate(float a, float b);
}

private Object operate(int a, int b, MathOperartor math){
    return math.operate(a,b);
}
private Object operate(float a, float b, MathOperartor math){
    return math.operate(a,b);
}

请让我知道我在这里做错了什么并提出修复建议...

更新:

好的,所以我理解了功能接口的概念,我的问题也是关于在上面的代码中实现我想要做的事情,我找到了几种方法来做到这一点。

感谢大家的宝贵回答!

【问题讨论】:

  • 你需要在那个接口中只有一个抽象方法,寻找功能接口。
  • "这个表达式的目标类型必须是函数式接口" => 嗯...MathOperartor 类型不是functional interface
  • 扩大类型转换可以由JVM自动完成,不需要两种方法来操作。一个函数式接口可以有一个抽象方法。

标签: java lambda java-8


【解决方案1】:

functional interface 必须是 SAM 接口:

一个函数式接口只有一个抽象方法。由于默认方法有一个实现,它们不是抽象的。如果一个接口声明了一个覆盖 java.lang.Object 的公共方法之一的抽象方法,这也不会计入接口的抽象方法计数,因为该接口的任何实现都将具有来自 java.lang.Object 或其他地方的实现。

你的接口声明了 2 个 abstract 方法,lambda 表达式不知道该去哪里,而 lambda 表达式是该接口的一个实例,这意味着它必须实现在界面。但是您可以添加默认方法来解决这种情况下的问题,例如:

interface MathOperartor{
  //it also can be removed, since a int can cast to a float automatically
  default Object operate(int a, int b){
     return operate((float)a, (float)b);
  }
  public Object operate(float a, float b);
}

【讨论】:

  • 谢谢!这解释了我的疑问并解决了代码中的错误。
  • @Balu 一点也不。这是我的荣幸。
【解决方案2】:

通常其他答案是正确的,@FunctionalInterface 是一个具有单个抽象方法的方法,除了那些在Object 中声明的方法。这仍然是合法的:

    @FunctionalInterface
    static interface Testable {

       public abstract String toString();

       public abstract void test();
    }

【讨论】:

    【解决方案3】:

    函数式接口中 lambda 的目标,也称为 SAM(单一抽象方法)接口。 以下是运行示例的方法:

    @FunctionalInterface
    public interface MathOperator<T> {
         T operate(T a,T b);
    }
    
    public class MathOperations {
        public static void main(String[] args) {
    
            MathOperator<Integer> add = (a, b) -> a + b;
            MathOperator<Integer> sub = (a, b) -> a - b;
    
            System.out.println(add.operate(1, 2));
            System.out.println(sub.operate(2, 1));
    
        }
    
    }
    

    希望对你有帮助

    【讨论】:

      【解决方案4】:

      Functional Interface 最多只能有一个抽象方法。

      【讨论】:

        【解决方案5】:

        一种信息性注释类型,用于指示接口类型声明旨在成为功能接口。

        函数式接口只有一个抽象方法。由于默认方法有一个实现,它们不是抽象的。如果一个接口声明了一个覆盖 java.lang.Object 的公共方法之一的抽象方法,这也不会计入接口的抽象方法计数,因为该接口的任何实现都将具有来自 java.lang.Object 或其他地方的实现。

        示例:

        @FunctionalInterface
        public interface SimpleFuncInterface {
          public void doWork();
        }
        

        但是一个接口可以有一个抽象方法,但可以有任意数量的默认方法,并且该接口仍然被称为函数式接口。

        示例:

        因此,您的代码将转换为:

        interface MathOperartor {
        
            default Object operate(int a, int b) {
                return operate((float) a, (float) b);
            }
        
            public Object operate(float a, float b);
        
        }
        

        函数式接口的实例可以使用 lambda 表达式、方法引用或构造函数引用来创建。

        但是,无论接口声明中是否存在 FunctionalInterface 注释,编译器都会将满足函数式接口定义的任何接口视为函数式接口。

        【讨论】:

          【解决方案6】:

          基本上,您的界面只能有一种方法。你不能超载它们

          【讨论】:

            猜你喜欢
            • 2014-06-19
            • 1970-01-01
            • 2017-11-16
            • 1970-01-01
            • 2015-04-17
            • 1970-01-01
            • 2015-06-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多