How to refer to super class version of a method using super::methodName in lamda expression

Viewed 1309

I'm learning Lambda expressions and method references in Java 8 and see that we can refer to the super-class version of a method by use of 'super', as:

super::name

But when I do this, it is not working. Here is the sample code:

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

Please tell me, am I implementing this code wrong? From what I understood, we can pass a method "X" as reference in place where implementation for method "Y" of a functional interface is expected since method "X" satisfies the conditions and behavior of method "Y" and could potentially replace method "Y" in that situation.

Is this not right,did I get methods references in the wrong way?

Thanks for your inputs on this :)

2 Answers

From the JLS:

The form super.Identifier refers to the field named Identifier of the current object, but with the current object viewed as an instance of the superclass of the current class.

[...]

The forms using the keyword super are valid only in an instance method, instance initializer, or constructor of a class, or in the initializer of an instance variable of a class. If they appear anywhere else, a compile-time error occurs.

You are calling super from a class type, thus the compilation error.

As many suggest in the comment you should just pass A::Func in the funcOp method.


Note that you won't be able to call super from your Func method either, as it's a static method, so it's not tied to a class instance.


Edit following OP's comment

You can use the super keyword from an instance method (so, if you remove static) and it'd look like this:

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

super and this keywords are reference variable that refers to some object. In other words it belongs to instance of the class.

You can do something like this if your looking for alternate approach rather than 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);
}

}

And in Test class main method

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

Output

Enter a number: 1
1
Related