Java 8 lambda Void argument

前端 未结 9 626
臣服心动
臣服心动 2020-12-12 08:30

Let\'s say I have the following functional interface in Java 8:

interface Action {
   U execute(T t);
}

And for some cases I ne

相关标签:
9条回答
  • 2020-12-12 09:08

    That is not possible. A function that has a non-void return type (even if it's Void) has to return a value. However you could add static methods to Action that allows you to "create" a Action:

    interface Action<T, U> {
       U execute(T t);
    
       public static Action<Void, Void> create(Runnable r) {
           return (t) -> {r.run(); return null;};
       }
    
       public static <T, U> Action<T, U> create(Action<T, U> action) {
           return action;
       } 
    }
    

    That would allow you to write the following:

    // create action from Runnable
    Action.create(()-> System.out.println("Hello World")).execute(null);
    // create normal action
    System.out.println(Action.create((Integer i) -> "number: " + i).execute(100));
    
    0 讨论(0)
  • 2020-12-12 09:11

    Add a static method inside your functional interface

    package example;
    
    interface Action<T, U> {
           U execute(T t);
           static  Action<Void,Void> invoke(Runnable runnable){
               return (v) -> {
                   runnable.run();
                    return null;
                };         
           }
        }
    
    public class Lambda {
    
    
        public static void main(String[] args) {
    
            Action<Void, Void> a = Action.invoke(() -> System.out.println("Do nothing!"));
            Void t = null;
            a.execute(t);
        }
    
    }
    

    Output

    Do nothing!
    
    0 讨论(0)
  • 2020-12-12 09:12

    The syntax you're after is possible with a little helper function that converts a Runnable into Action<Void, Void> (you can place it in Action for example):

    public static Action<Void, Void> action(Runnable runnable) {
        return (v) -> {
            runnable.run();
            return null;
        };
    }
    
    // Somewhere else in your code
     Action<Void, Void> action = action(() -> System.out.println("foo"));
    
    0 讨论(0)
  • 2020-12-12 09:12

    I don't think it is possible, because function definitions do not match in your example.

    Your lambda expression is evaluated exactly as

    void action() { }
    

    whereas your declaration looks like

    Void action(Void v) {
        //must return Void type.
    }
    

    as an example, if you have following interface

    public interface VoidInterface {
        public Void action(Void v);
    }
    

    the only kind of function (while instantiating) that will be compatibile looks like

    new VoidInterface() {
        public Void action(Void v) {
            //do something
            return v;
        }
    }
    

    and either lack of return statement or argument will give you a compiler error.

    Therefore, if you declare a function which takes an argument and returns one, I think it is impossible to convert it to function which does neither of mentioned above.

    0 讨论(0)
  • 2020-12-12 09:18

    The lambda:

    () -> { System.out.println("Do nothing!"); };
    

    actually represents an implementation for an interface like:

    public interface Something {
        void action();
    }
    

    which is completely different than the one you've defined. That's why you get an error.

    Since you can't extend your @FunctionalInterface, nor introduce a brand new one, then I think you don't have much options. You can use the Optional<T> interfaces to denote that some of the values (return type or method parameter) is missing, though. However, this won't make the lambda body simpler.

    0 讨论(0)
  • 2020-12-12 09:20

    You can create a sub-interface for that special case:

    interface Command extends Action<Void, Void> {
      default Void execute(Void v) {
        execute();
        return null;
      }
      void execute();
    }
    

    It uses a default method to override the inherited parameterized method Void execute(Void), delegating the call to the simpler method void execute().

    The result is that it's much simpler to use:

    Command c = () -> System.out.println("Do nothing!");
    
    0 讨论(0)
提交回复
热议问题