Java Pass Method as Parameter

后端 未结 16 992
滥情空心
滥情空心 2020-11-22 02:17

I am looking for a way to pass a method by reference. I understand that Java does not pass methods as parameters, however, I would like to get an alternative.

I\'ve

相关标签:
16条回答
  • 2020-11-22 02:44

    If you don't need these methods to return something, you could make them return Runnable objects.

    private Runnable methodName (final int arg) {
        return (new Runnable() {
            public void run() {
              // do stuff with arg
            }
        });
    }
    

    Then use it like:

    private void otherMethodName (Runnable arg){
        arg.run();
    }
    
    0 讨论(0)
  • 2020-11-22 02:46

    I'm not a java expert but I solve your problem like this:

    @FunctionalInterface
    public interface AutoCompleteCallable<T> {
      String call(T model) throws Exception;
    }
    

    I define the parameter in my special Interface

    public <T> void initialize(List<T> entries, AutoCompleteCallable getSearchText) {.......
    //call here
    String value = getSearchText.call(item);
    ...
    }
    

    Finally, I implement getSearchText method while calling initialize method.

    initialize(getMessageContactModelList(), new AutoCompleteCallable() {
              @Override
              public String call(Object model) throws Exception {
                return "custom string" + ((xxxModel)model.getTitle());
              }
            })
    
    0 讨论(0)
  • 2020-11-22 02:47

    I didn't find any example explicit enough for me on how to use java.util.function.Function for simple method as parameter function. Here is a simple example:

    import java.util.function.Function;
    
    public class Foo {
    
      private Foo(String parameter) {
        System.out.println("I'm a Foo " + parameter);
      }
    
      public static Foo method(final String parameter) {
        return new Foo(parameter);
      }
    
      private static Function parametrisedMethod(Function<String, Foo> function) {
        return function;
      }
    
      public static void main(String[] args) {
        parametrisedMethod(Foo::method).apply("from a method");
      }
    }
    

    Basically you have a Foo object with a default constructor. A method that will be called as a parameter from the parametrisedMethod which is of type Function<String, Foo>.

    • Function<String, Foo> means that the function takes a String as parameter and return a Foo.
    • The Foo::Method correspond to a lambda like x -> Foo.method(x);
    • parametrisedMethod(Foo::method) could be seen as x -> parametrisedMethod(Foo.method(x))
    • The .apply("from a method") is basically to do parametrisedMethod(Foo.method("from a method"))

    Which will then return in the output:

    >> I'm a Foo from a method
    

    The example should be running as is, you can then try more complicated stuff from the above answers with different classes and interfaces.

    0 讨论(0)
  • 2020-11-22 02:49

    Since Java 8 there is a Function<T, R> interface (docs), which has method

    R apply(T t);
    

    You can use it to pass functions as parameters to other functions. T is the input type of the function, R is the return type.

    In your example you need to pass a function that takes Component type as an input and returns nothing - Void. In this case Function<T, R> is not the best choice, since there is no autoboxing of Void type. The interface you are looking for is called Consumer<T> (docs) with method

    void accept(T t);
    

    It would look like this:

    public void setAllComponents(Component[] myComponentArray, Consumer<Component> myMethod) {
        for (Component leaf : myComponentArray) {
            if (leaf instanceof Container) { 
                Container node = (Container) leaf;
                setAllComponents(node.getComponents(), myMethod);
            } 
            myMethod.accept(leaf);
        } 
    }
    

    And you would call it using method references:

    setAllComponents(this.getComponents(), this::changeColor);
    setAllComponents(this.getComponents(), this::changeSize); 
    

    Assuming that you have defined changeColor() and changeSize() methods in the same class.


    If your method happens to accept more than one parameter, you can use BiFunction<T, U, R> - T and U being types of input parameters and R being return type. There is also BiConsumer<T, U> (two arguments, no return type). Unfortunately for 3 and more input parameters, you have to create an interface by yourself. For example:

    public interface Function4<A, B, C, D, R> {
    
        R apply(A a, B b, C c, D d);
    }
    
    0 讨论(0)
  • 2020-11-22 02:49

    While this is not yet valid for Java 7 and below, I believe that we should look to the future and at least recognize the changes to come in new versions such as Java 8.

    Namely, this new version brings lambdas and method references to Java (along with new APIs, which are another valid solution to this problem. While they still require an interface no new objects are created, and extra classfiles need not pollute output directories due to different handling by the JVM.

    Both flavors(lambda and method reference) require an interface available with a single method whose signature is used:

    public interface NewVersionTest{
        String returnAString(Object oIn, String str);
    }
    

    Names of methods will not matter from here on. Where a lambda is accepted, a method reference is as well. For example, to use our signature here:

    public static void printOutput(NewVersionTest t, Object o, String s){
        System.out.println(t.returnAString(o, s));
    }
    

    This is just a simple interface invocation, up until the lambda1 gets passed:

    public static void main(String[] args){
        printOutput( (Object oIn, String sIn) -> {
            System.out.println("Lambda reached!");
            return "lambda return";
        }
        );
    }
    

    This will output:

    Lambda reached!
    lambda return
    

    Method references are similar. Given:

    public class HelperClass{
        public static String testOtherSig(Object o, String s){
            return "real static method";
        }
    }
    

    and main:

    public static void main(String[] args){
        printOutput(HelperClass::testOtherSig);
    }
    

    the output would be real static method. Method references can be static, instance, non-static with arbitrary instances, and even constructors. For the constructor something akin to ClassName::new would be used.

    1 This is not considered a lambda by some, as it has side effects. It does illustrate, however, the use of one in a more straightforward-to-visualize fashion.

    0 讨论(0)
  • 2020-11-22 02:50

    I did not found any solution here that show how to pass method with parameters bound to it as a parameter of a method. Bellow is example of how you can pass a method with parameter values already bound to it.

    1. Step 1: Create two interfaces one with return type, another without. Java has similar interfaces but they are of little practical use because they do not support Exception throwing.
    
    
        public interface Do {
        void run() throws Exception;
        }
    
    
        public interface Return {
            R run() throws Exception;
        }
    
    
    1. Example of how we use both interfaces to wrap method call in transaction. Note that we pass method with actual parameters.
    
    
        //example - when passed method does not return any value
        public void tx(final Do func) throws Exception {
            connectionScope.beginTransaction();
            try {
                func.run();
                connectionScope.commit();
            } catch (Exception e) {
                connectionScope.rollback();
                throw e;
            } finally {
                connectionScope.close();
            }
        }
    
        //Invoke code above by 
        tx(() -> api.delete(6));
    
    

    Another example shows how to pass a method that actually returns something

    
    
            public  R tx(final Return func) throws Exception {
        R r=null;
        connectionScope.beginTransaction();
        try {
                    r=func.run();
                    connectionScope.commit();
                } catch (Exception e) {
                    connectionScope.rollback();
                    throw e;
                } finally {
                    connectionScope.close();
                }
            return r;
            }
            //Invoke code above by 
            Object x= tx(() -> api.get(id));
    
    
    0 讨论(0)
提交回复
热议问题