启动和调用 Java 方法引用的标准模式

Standard pattern of initiating and calling the Java method references

我有一个 ClassA 对象,它在 ClassB1ClassB2 对象中设置方法引用。 ClassB1ClassB2 对象稍后将使用此方法引用,而 运行 他们的方法。但是,有时我们没有设置方法参考:

public class ClassA {
    public ClassA() {
        ClassB1 objB1 = new ClassB1();
        ClassB2 objB2 = new ClassB2();
        objB1.setFuncitonA(this::functionA);
        objB2.setFuncitonA(this::functionA);
        objB1.functionB();
        objB2.functionB();
    }
    public void functionA(Integer x) {
        x *= 2;
    }
}

public class ClassB1 {
    private Integer intObjB = new Integer(2);
    private Consumer<Integer> functionA = null;
    public void functionB() {
        if(functionA != null) {
            functionA.accept(intObjB);
        }
    }
    public void setFuncitonA(Consumer<Integer> functionA) {
        this.functionA = functionA;
    }
}

public class ClassB2 {
    private Integer intObjB = new Integer(2);
    private Consumer<Integer> functionA = this::defaultFunctionA;
    public void functionB() {
        functionA.accept(intObjB);
    }
    public void setFuncitonA(Consumer<Integer> functionA) {
        this.functionA = functionA;
    }
    public void defaultFunctionA(Integer intObj) {
        return;
    }
}

它应该像 ClassB1 中那样还是像 ClassB2 中那样,或者,这有关系吗?编写此类代码的标准模式是什么?

消除 if 语句始终是首选。

此外,消除 null 变量总是更好。

因此,目前 ClassB2 方法更好。

这种实现决策有一个术语:延迟实例化您的字段,或急切实例化您的字段。

ClassB1 延迟实例化 functionA 消费者。这告诉维护者(包括你自己)这个消费者并不总是每个新实例所必需的,并且在某些情况下拥有它 null 是安全的。它 确实 意味着你在使用它时必须回头看,就像 null 检查的情况一样。

ClassB2 急切地实例化 functionA 消费者。这告诉维护者(包括你自己)这个消费者在实例化时是 required。这意味着您可以避免愚蠢的 null 检查它是否真的是您在实例化时知道的东西(在这种情况下,它 您知道或可以获得的东西)。

然后标准模式变为:

  • 如果您愿意在 使用前检查字段(或变量)是否 null ,则延迟实例化该字段。
  • 如果必须确定该字段(或变量)不null 使用前,则急切实例化领域。

没有硬性规定来使用或偏爱其中一个。这在很大程度上取决于您的用例。