如何将一个函数作为参数传递给另一个函数

3
我希望能够将一个函数作为参数传递给另一个函数。例如:
void myFunction(boolean coondition, void function())
{
   if(condition) {
     function();
   }
}

这在Java 8中是否可行?

1
自从1.1版本以来就可以了。你可以传递一个boolean和一个Runnable - Paul Boddington
这位可怜的提问者询问的是Java 8版本,而不是其他任何版本。 - Kick Buttowski
如果您有一个函数,那么您可以传递一个函数。不幸的是,函数需要具有返回类型(最好可装箱为对象或已经是对象),而您在此处传递的内容没有返回类型。因此,在Java中它不是一个函数。 - Vogel612
3个回答

4
不,你不能传递方法。
但是有一个简单的解决方法:传递一个Runnable。
void myFunction(boolean coondition, Runnable function)
{
   if(condition) {
     function.run();
   }
}

并且可以像这样调用它:(使用旧的语法)

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

或者在Java 8中使用新的lambda语法(这基本上是上述代码的缩写):

myFunction(condition, () -> {otherFunction();}}

3

是的,这是可能的。假设您的函数什么也不做,只需传递一个 Runnable

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

假设您有一个名为function的函数,它如下所示(void可以替换为不会被使用的返回类型):
private void function() {/*whatever*/}

您可以使用lambda表达式这样调用它。
myFunction(true, () -> function());

或者在Java 1.1-1.7中像这样

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

0
在Java中,除了原始类型,几乎所有东西都是对象。但是你可以使用functional interfaces来处理函数。 在Java 8之前,已经有使用情况,通过实例化匿名类经常使用功能接口:

如果您想将函数作为参数传递,有许多表达方式:

假设您想要应用某些函数(例如平方一个值),如果满足一些条件(例如这是一个偶数),则可以使用以下方法:

// 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(" ");      
        }
    }
}

你可以进行测试:

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
而且这也可以用lambda表达式来写:
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);
}

或者直接:

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

而且,您还可以将成员方法用作函数,只要它们具有功能接口签名。

// 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);     
    }
}

在一个包含10个 Foo 对象的列表上进行测试:

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
可以简写为:
public static void main(String[] args) {
    IntStream.range(0, 10)
       .mapToObj(i -> new Foo())
       .filter((Foo x) -> x.getBar() % 2 == 0)
       .forEach(Foo::println);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接