如何在lamda表达式中使用super :: methodName引用方法的超类版本

时间:2018-10-30 12:09:37

标签: java lambda java-8 method-reference

我正在学习Java 8中的Lambda表达式和方法引用,并且看到我们可以通过使用'super'来引用方法的超类版本,

super :: name

但是当我这样做时,它不起作用。这是示例代码:

interface MyInterface {
int someFunc(int x);
}

    class A {
    static int Func(int y) {
        // return (int) (Math.random() * y);
        return y;
    }
}

class B extends A {
    static int Func(int y) {
        // return (int) (Math.random() * y);
        return y + 1;
    }
}

public class Test {
    public static void main(String[] args) {
        System.out.print("Enter a number: ");
        java.util.Scanner scanner = new java.util.Scanner(System.in);
        int result = funcOp(B::Func, scanner.nextInt()); // <-This works.
//int result = funcOp(B.super::Func, scanner.nextInt());  <--This is not working. 
//Getting: error: not an enclosing class: B
            int result = funcOp(B.super::Func, scanner.nextInt());
                                 ^
        scanner.close();
        System.out.println(result);
    }

    static int funcOp(MyInterface mI, int num) {
        return mI.someFunc(num);
    }
}

请告诉我,我实现此代码有误吗?据我了解,由于方法“ X”满足方法“ Y”的条件和行为,并且可以潜在地替代方法,因此我们可以通过方法“ X”作为参考,以实现功能接口方法“ Y”的实现。在这种情况下为“ Y”。

这不对吗,我是否以错误的方式获得了方法引用?

感谢您对此的投入:)

2 个答案:

答案 0 :(得分:5)

来自the JLS

  

super.Identifier形式是指当前对象的名为Identifier的字段,但当前对象被视为当前类的超类的实例。

     

[...]

     

使用关键字super的表单仅在实例方法,实例初始化器或类的构造函数或类的实例变量的初始化器中有效。 如果它们出现在其他任何地方,则会发生编译时错误

您正在从类类型中调用super,从而导致编译错误。

许多人在评论中建议您只需在A::Func方法中传递funcOp


请注意,您也将无法从super方法中调用Func,因为它是static方法,因此它并不与类实例相关。


根据OP的评论进行编辑

您可以从实例方法中使用super关键字(因此,如果您删除了static的话),它看起来像这样:

class B extends A {
    int Func(int y) {
        // e.g:
        if (y > 10) {
            return super.Func(y); // call Func from the parent class
        }
        return y + 1;
    }
}

答案 1 :(得分:0)

super this 关键字是引用某个对象的参考变量。换句话说,它属于该类的实例。

如果您要寻找替代方法而不是 A :: Func

,则可以执行以下操作
class B extends A {

static int Func(int y) {
    // return (int) (Math.random() * y);
    return y + 1;
}

public int getSuperFunc(int y)
{
    //call A class Func(int y)
    return super.Func(y);
}

}

在Test类的主方法中

System.out.print("Enter a number: ");
java.util.Scanner scanner = new java.util.Scanner(System.in);
//int result = funcOp(B::Func, scanner.nextInt()); // <-This works.

B b=new B();              
int result1 = funcOp(b::getSuperFunc, scanner.nextInt()); // <-This works.

scanner.close();
System.out.println(result1);

输出

Enter a number: 1
1