5

I have a class with bunch of methods. In another class, I need to write a method, that handles the input values. To that method, I want to pass the method of the class that I want to call. How can we do that with Java after 1.8?

There are similar questions already, but those usually assume that we can use an interface with a single method, therefore can use lambda expressions, etc.

class MyClass {
    public Object myToString(String a) {
        return new String(a);
    }

    public Object myToString(String a, String b) {
       return new String(a + ", " + b);
    }

    public Object mySum(int a) {
        return new Integer(a);
    }

    public Object mySum(int a, int b) {
        return new Integer(a + b);
    }
}

class Test {
    public Object handleInputs(MyClass myClass, MethodAsParameter theMethod, List<Object> inputs) {
        if (type of inputs are Strings) {
            myClass.myToString(inputs.get(0));
        } else if (.....) {
            myClass.mySum(inputs.get(0));
        }
    }
}
2
  • You don't pass the method, you pass the value to those methods and get a result back.(After creating an instance of the class in which your functions reside). Commented Mar 14, 2019 at 19:05
  • You are not using theMethod in handleInputs Commented Mar 14, 2019 at 20:01

3 Answers 3

7

Since Java 8 you can use method reference. Method references can be assigned to Function<A, B> functional interface variables and their subclasses.

For example, method with such signature:

class Test {
    public static int DoSomething(String s) {...}
}

can be assigned to a Function<String, Integer> variable like:

Function<String, Integer> method = Test::DoSomething;

and then called:

int result = method.apply("Hello!");

So with small improvements in your code, this is the way you can use your methods as method references and passed to other function as parameters.

class MyClass {

    public static String myToString(String a, String b) {
        return a + ", " + b;
    }

    //notice the boxing in here
    public static int mySum(int a, int b) {
        return a + b;
    }
    
    //not kind of an revolutionary function, just for demonstration
    public static<T> T Invoke(BinaryOperator<T> bo, T o1, T o2) {
        return bo.apply(o1, o2);
    }


    public static void main(String[] args) {

        int sum = Invoke(MyClass::mySum, 10, 20);
        String str = Invoke(MyClass::myToString, "a", "b");
    
        System.out.println(sum);
        System.out.println(str);
    
}

}

Sign up to request clarification or add additional context in comments.

Comments

2

I think something like this is as far as you would get:

import java.util.List;
import java.util.Arrays;
import java.util.function.Function;
import java.util.function.BiFunction;

class MyClass {
    public Object myToString(String a) {
        return new String(a);
    }

    public Object myToString(String a, String b) {
       return new String(a + ", " + b);
    }

    public Object mySum(int a) {
        return Integer.valueOf(a);
    }

    public Object mySum(int a, int b) {
        return Integer.valueOf(a + b);
    }
}

public class MethodParams {
    public static Object handleInputs(Function<Object,Object> method, List<Object> inputs) {
        return method.apply(inputs.get(0));
    }

    public static Object handleInputs(BiFunction<Object,Object,Object> method, List<Object> inputs) {
        return method.apply(inputs.get(0), inputs.get(1));
    }    

    public static void main(String args[]) {
        MyClass mc = new MyClass();

        String str = (String)handleInputs((a) -> mc.myToString((String)a), Arrays.asList("string"));
        System.out.println(str); // string

        Integer sum = (Integer)handleInputs((a) -> mc.mySum((int)a), Arrays.asList(1));
        System.out.println(sum); // 1

        Integer sum2 = (Integer)handleInputs((a,b) -> mc.mySum((int)a, (int)b), Arrays.asList(1, 2));
        System.out.println(sum2); // 3
    }
}

Not very nice, but at least you have some leeway as to which method you want to use. Code as demonstrated here has lots of casts due to using Objects - using generic types as demonstrated by t2dohx is better way of doing this, but even further from your question.

Comments

0

Here is a simple example:

public class TestMain {

    public static void main(String [] args) {
        Long a = 15L, b = 20L;
        Long sum = combineTwoNumbers(a, b, (p1, p2) -> p1 + p2);
        Long product = combineTwoNumbers(a, b, (p1, p2) -> p1 * p2);
        System.out.println("Sum is " + sum);
        System.out.println("Product is " + product);
    }

    public static Long combineTwoNumbers(Long a, Long b, BiFunction <Long, Long, Long> combiner) {
        return combiner.apply(a, b);
    }
}

Here, the functional parameter is BiFunction, which takes two parameters in input and returns an output. Specifically, it takes two long numbers and produces a third one as a result. The name of the method is kept generic so that it can cover more instances of different functions that may take place. In our example we are passing a sum and a product function as you can see.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.