Why can we not use default methods in lambda expressions?

前端 未结 5 1834
既然无缘
既然无缘 2020-12-24 01:25

I was reading this tutorial on Java 8 where the writer showed the code:

interface Formula {
    double calculate(int a);

    default double sqrt(int a) {
           


        
5条回答
  •  不思量自难忘°
    2020-12-24 01:45

    That's not exactly true. Default methods can be used in lambda expressions.

    interface Value {
        int get();
    
        default int getDouble() {
            return get() * 2;
        }
    }
    
    public static void main(String[] args) {
        List list = Arrays.asList(
                () -> 1,
                () -> 2
            );
        int maxDoubled = list.stream()
            .mapToInt(val -> val.getDouble())
            .max()
            .orElse(0);
        System.out.println(maxDoubled);
    }
    

    prints 4 as expected and uses a default method inside a lambda expression (.mapToInt(val -> val.getDouble()))

    What the author of your article tries to do here

    Formula formula = (a) -> sqrt( a * 100);
    

    is to define a Formula, which works as functional interface, directly via a lambda expression.

    That works fine, in above example code, Value value = () -> 5 or with Formula as interface for example

    Formula formula = (a) -> 2 * a * a + 1;
    

    But

    Formula formula = (a) -> sqrt( a * 100);
    

    fails because it's trying to access the (this.)sqrt method but it can't. Lambdas as per spec inherit their scope from their surroundings, meaning that this inside a lambda refers to the same thing as directly outside of it. And there is no sqrt method outside.

    My personal explanation for this: Inside the lambda expression, it's not really clear to what concrete functional interface the lambda is going to be "converted". Compare

    interface NotRunnable {
        void notRun();
    }
    
    private final Runnable r = () -> {
        System.out.println("Hello");
    };
    
    private final NotRunnable r2 = r::run;
    

    The very same lambda expression can be "cast" to multiple types. I think of it as if a lambda doesn't have a type. It's a special typeless function that can be used for any Interface with the right parameters. But that restriction means that you can't use methods of the future type because you can't know it.

提交回复
热议问题