Java Lambdas:将方法名称作为参数发送

时间:2017-04-06 19:07:19

标签: java lambda interface functional-programming

我遇到了一个问题,其中我的类包含多个具有大量重复代码的方法。这背后的原因是每个方法遍历一个条目列表并调用特定的入口方法。

在代码中......

LowLevelClass类具有以下结构:

public class LowLevelClass {

    // constructor omitted

    public boolean doSomethingA() {
        // some non-duplicated code
        return true;
    }

    public boolean doSomethingB() {
        // some non-duplicated code
        return true;
    }

    public boolean doSomethingC() {
        // some non-duplicated code
        return true;
    }
}

顶级类包含一个LowLevelClasses列表,并且具有相同数量的方法,但这一次有很多重复:

public class HighLevelClass {

    private List<LowLevelClass> classes = new ArrayList<>();

    public HighLevelClass() {
        this.classes.add(new LowLevelClass(/* params */));
        this.classes.add(new LowLevelClass(/* params */));
        this.classes.add(new LowLevelClass(/* params */));
    }

    public void doA() {
        System.out.println("Doing ...");
        for (LowLevelClass entry : classes) {
            System.out.println("Doing something...");
            entry.doSomethingA();
            System.out.println("Done");
        }
    }

    public void doB() {
        System.out.println("Doing ...");
        for (LowLevelClass entry : classes) {
            System.out.println("Doing something...");
            entry.doSomethingB();
            System.out.println("Done");
        }
    }

    public void doC() {
        System.out.println("Doing ...");
        for (LowLevelClass entry : classes) {
            System.out.println("Doing something...");
            entry.doSomethingC();
            System.out.println("Done");
        }
    }
}

我的目标是拥有以下形式的东西:

public class HighLevelClass {

    private List<LowLevelClass> classes = new ArrayList<>();

    public HighLevelClass() {
        this.classes.add(new LowLevelClass());
        this.classes.add(new LowLevelClass());
        this.classes.add(new LowLevelClass());
    }

    public void doSomething(Lambda /* Functional interface*/ operation) {
        System.out.println("Doing A");
        for (LowLevelClass entry : classes) {
            System.out.println("Doing something...");
            entry.operation; // or something else...
            System.out.println("Done");
        }
    }

    public void doSomethingA() {
        // my goal... and maybe in totally wrong direction is to send something in form of...
        return doSomething(LowLevelClass::doSomethingA);
    }

    // etc
}

这可以在Java 8中使用Lambdas完成吗?换句话说,我可以定义要对给定列表的每个条目执行的方法吗?

编辑1

Jorn Vernee Joffrey 提供的答案是正确的!

最终,解决方案是使用Predicate。 (参见编辑2为什么我最终没有使用消费者......)

公共类HighLevelClass {

private List<LowLevelClass> classes = new ArrayList<>();

public HighLevelClass() {
    this.classes.add(new LowLevelClass());
    this.classes.add(new LowLevelClass());
    this.classes.add(new LowLevelClass());
}

public boolean doSomething(Predicate<LowLevelClass> function) {
    System.out.println("Doing A");
    for (LowLevelClass entry : classes) {
        System.out.println("Doing something...");
        boolean val = function.test(entry);
        System.out.println("Done " + val);
    }
    return someEndVerdict; 
}

public boolean doSomethingA() {
    return doSomething(LowLevelClass::doSomethingA);
}

// etc

}

编辑2

我在HighLevelClass中的初始方法不包含布尔返回类型。这就是为什么我使用谓词(Predicate,作为对消费者的影响,返回适合我的布尔值更好 - 而且我忘了最初提到的:((()

感谢您的帮助和时间!

1 个答案:

答案 0 :(得分:2)

你不应该混淆调用方法的方式,这可能涉及或不涉及lambda,以及编写方法的方式,这涉及到找到正确的方法参数类型。

当你编写一个方法时,你需要关注你的论点&#39;类型。如果其中一个是表示函数的对象,那么您需要了解此函数应该匹配的相应签名,这将为您提供应作为参数类型放置的函数接口。

在您的情况下,您期望一个函数采用类型LowLevelClass的1个参数并且不返回任何值。您可能会对此感到惊讶,但您需要将实例方法视为将类的实例(this)作为额外的第一个参数(而不是静态方法)的函数。

因此,Consumer<LowLevelClass>接口就是您想要的:

public void doSomething(Consumer<LowLevelClass> operation) {
    System.out.println("Doing A");
    for (LowLevelClass entry : classes) {
        System.out.println("Doing something...");
        operation.accept(entry); // or something else...
        System.out.println("Done");
    }
}

public void doSomethingA() {
    return doSomething(LowLevelClass::doSomethingA);
}