我有一个ClassA
对象,用于在ClassB1
和ClassB2
对象中设置方法引用。ClassB1
和ClassB2
对象稍后将在运行其方法时使用此方法引用。但是,有时我们不设置方法引用:
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
,或者,这有什么关系吗?编写此类代码的标准模式是什么?
这种实现决策有命名法:懒惰地实例化你的字段,或者急切地实例化你的字段。
ClassB1
懒惰地实例化functionA
使用者。 这告诉维护者(包括你自己),这个消费者并不总是每个新实例都需要的,并且在某些情况下null
它是安全的。 这确实意味着您在使用它时必须仔细观察,就像null
检查一样。
ClassB2
急切地实例化functionA
消费者。 这告诉维护者(包括你自己)在实例化时需要这个消费者。 这意味着您可以避免愚蠢null
检查它是否真的是您在实例化时知道的东西(在这种情况下,它是您知道或可以得到的东西)。
然后,标准模式变为:
- 如果您愿意在使用前检查字段(或变量)是否
null
,请延迟实例化该字段。 - 如果必须确保字段(或变量)在使用前未
null
,请急切地实例化该字段。
没有硬性规定可以使用或更喜欢一个。 这将在很大程度上取决于您的用例。
始终首选消除if
语句。
此外,消除null
变量总是更好。
因此,到目前为止,ClassB2
方法更好。