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

The*_*ool 2 java lambda java-8 method-reference

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

超级::名

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

请告诉我,我实现这个代码错了吗?根据我的理解,我们可以传递方法"X"作为参考,其中预期功能接口的方法"Y"的实现,因为方法"X"满足方法"Y"的条件和行为并且可能替代方法在这种情况下"Y".

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

感谢您对此的意见:)

Mar*_*cak 5

来自JLS:

形式super.Identifier引用当前对象的名为Identifier的字段,但将当前对象视为当前类的超类的实例.

[...]

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

您正在super从类类型调用,因此编译错误.

正如许多评论建议你应该只是传递A::FuncfuncOp方法.


请注意,您将无法super从您的Func方法调用,因为它是一个static方法,因此它不依赖于类实例.


编辑OP的评论

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 或者仅使用方法句柄作为案例:`int Func(int y){Function <Integer,Integer> f = super :: Func; 返回y> 10?f.apply(y):y + 1; }` (2认同)