Why is this type inference not working with this Lambda expression scenario?

后端 未结 6 760
小蘑菇
小蘑菇 2020-12-24 01:23

I have a weird scenario where type inference isn\'t working as I\'d expect when using a lambda expression. Here\'s an approximation of my real scenario:

stat         


        
6条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-12-24 02:14

    Problem

    Value will infer to type Value because you interpreted the lambda wrong. Think of it, like you call with the lambda directly the apply method. So what you do is:

    Boolean apply(Value value);
    

    and this is correctly inferred to:

    Boolean apply(Value value);
    
    
    

    since you haven't given the type for Value.

    Simple Solution

    Call the lambda in a correct way:

    Foo.foo((Value value) -> true).booleanValue();
    

    this will be inferred to:

    Boolean apply(Value value);
    

    (My) Recommended Solution

    Your solution should be a bit more clear. If you want a callback, then you need a type value which will be returned.

    I've made a generic Callback interface, a generic Value class and an UsingClass to show how to use it.

    Callback interface

    /**
     *
     * @param 

    The parameter to call * @param The return value you get */ @FunctionalInterface public interface Callback { public R call(P param); }

    Value class

    public class Value {
    
      private final T field;
    
      public Value(T field) {
        this.field = field;
      }
    
      public T getField() {
        return field;
      }
    }
    

    UsingClass class

    public class UsingClass {
    
      public T foo(Callback, T> callback, Value value) {
        return callback.call(value);
      }
    }
    

    TestApp with main

    public class TestApp {
    
      public static void main(String[] args) {
        Value boolVal = new Value<>(false);
        Value stringVal = new Value<>("false");
    
        Callback, Boolean> boolCb = (v) -> v.getField();
        Callback, String> stringCb = (v) -> v.getField();
    
        UsingClass usingClass = new UsingClass<>();
        boolean val = usingClass.foo(boolCb, boolVal);
        System.out.println("Boolean value: " + val);
    
        UsingClass usingClass1 = new UsingClass<>();
        String val1 = usingClass1.foo(stringCb, stringVal);
        System.out.println("String value: " + val1);
    
        // this will give you a clear and understandable compiler error
        //boolean val = usingClass.foo(boolCb, stringVal);
      }
    }
    

    提交回复
    热议问题