4

I would like pass a function as an parameter to another function. For example:

void myFunction(boolean coondition, void function())
{
   if(condition) {
     function();
   }
}

It this possible in Java 8?

3
  • 1
    It's been possible since 1.1. You can pass a boolean and a Runnable. Commented Mar 23, 2015 at 23:09
  • the poor op asked about Java 8 not any other version Commented Mar 23, 2015 at 23:15
  • Well you could pass a Function if you had one. Unfortunately functions are required to have a return type (preferrably boxable to or already an object) and what you pass here doesn't have a return type. As such it is not a Function in the java sense of it . Commented Mar 23, 2015 at 23:45

3 Answers 3

5

No, you can't pass methods.

But there is a simple workaround: pass a Runnable.

void myFunction(boolean coondition, Runnable function)
{
   if(condition) {
     function.run();
   }
}

and call it like this: (using the old syntax)

myFunction(condition, new Runnable() {
    @Override
    public void run() {
        otherFunction();
    }
});

or using the new lambda syntax in Java 8 (which is mostly shorthand for the above):

myFunction(condition, () -> {otherFunction();}}
Sign up to request clarification or add additional context in comments.

Comments

3

Yes, it is possible. Assuming your function does nothing, just pass a Runnable.

void myFunction(boolean condition, Runnable function)
{
   if(condition) {
     function.run();
   }
}

Assuming you have a function named function as such (void can be replaced by a return type, which will not be used):

private void function() {/*whatever*/}

you can call it like this using lambda expressions

myFunction(true, () -> function());

or like this in Java 1.1-1.7

myFunction(true, new Runnable(){public void run(){function();}});

Comments

0

In Java, quite everything is an object (but primitive types). But you can use functional interfaces to handle functions. Before Java 8, there was already use-cases where functional interfaces were used often through the instantiation of anonymous classes:

If you want to pass a function as a parameter, you have many ways to express that:

Let's say you want to apply some function (e.g. square a value) if some condition is met on the initial value (e.g. this is an even number):

// Return the square of a number 
static Function<Integer, Integer> square = new Function<Integer, Integer>() {
    @Override
    public Integer apply(Integer t) {
        return t*t;
    }       
};

// Return true is the parameter is an even number
static Predicate<Integer> isEven = new Predicate<Integer>() {
    @Override
    public boolean test(Integer t) {
        return (t % 2) == 0;
    }
};

// A generic function that prints for each x of the list
// xtrans(x) only if pred(x) is true.
public static <T, R> void printIf(Predicate<T> pred, Function<T, R> xtrans, List<T> xs) {
    for (T x : xs) {
        if (pred.test(x)) {
            System.out.print(xtrans.apply(x));      
            System.out.print(" ");      
        }
    }
}

You can test it:

public static void main(String[] args) {
    List<Integer> ints = IntStream.range(0, 10)
         .boxed()
         .collect(Collectors.toList());
    printIf(isEven, square, ints);
}

=> 0 4 16 36 64

And this can also be written with lambdas:

public static void main(String[] args) {
    List<Integer> ints = IntStream.range(0, 10).boxed().collect(Collectors.toList());

    Predicate<Integer> even = x -> (x % 2) == 0;
    Function<Integer, Integer> square = x -> x*x;

    printIf(even, square, ints);
}

Or directly:

    printIf(x -> (x % 2)==0, x -> x*x, ints);

And you can also use member methods as functions, provided they have a functional interface signature.

// Wrap a random integer between 0 and 10
public class Foo {
    static Random gen = new Random();
    int bar = gen.nextInt(10);
    public void println() { System.out.println(bar); }
    public int getBar() { return bar; }
}

// Execute doTo(x) if pred(x) is true
public static <T> void doToIf(Predicate<T> pred, Consumer<T> doTo, T x) {
    if (pred.test(x)) {
        doTo.accept(x);     
    }
}

Test it on a list of 10 Foo objects:

public static void main(String[] args) {
    List<Foo> foos = IntStream.range(0, 10)
         .mapToObj(i -> new Foo())
         .collect(Collectors.toList());

    for (Foo foo : foos) {
        doToIf((Foo x) -> x.getBar() % 2 == 0, Foo::println, foo);
    }
}

=> 6 2 0 0 4

Which can be shortened to:

public static void main(String[] args) {
    IntStream.range(0, 10)
       .mapToObj(i -> new Foo())
       .filter((Foo x) -> x.getBar() % 2 == 0)
       .forEach(Foo::println);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.