使用java供应商接口创建条件对象
我有一个方法如下:
void updateObject(ObjOne obj, SomeClass data) {
if(obj != null) {
obj.doSomething(data);
}
}
在updateObject多次调用,避免空检查在每一个地方,我想避免以下的:
// directly invoke doSomething conditionally.
if(obj != null) {
SomeClass data = getData();
obj.doSomething(data);
}
由于data仅在obj非空时使用,我想到了如下重构代码:
void updateObject(ObjOne obj, Supplier<SomeClass> data) {
if(obj != null) {
obj.doSomething(data.get());
}
}
这将SomeClass仅在需要时创建一个对象,而是创建一个Supplier类型的对象。
上述方法使用Supplier更好吗?
回答
性能取决于构建SomeClass实例的成本,换句话说,只创建一个而不创建Supplier一个SomeClass实例可以节省什么,以及不创建SomeClass实例的可能性。如果SomeClass在大多数情况下无论如何都创建了实例,显然您不能通过额外创建一个Supplier.
如果您在不知道费用和可能性的情况下设计 API,您可以提供这两种方法并让调用者决定使用哪种方法。这是一个既定的模式,例如
Objects.requireNonNull?(T obj, String message)对比Objects.requireNonNull?(T obj, Supplier<String> messageSupplier)
或者
Objects.requireNonNullElse?(T obj, T defaultObj)对比Objects.requireNonNullElseGet?(T obj, Supplier<? extends T> supplier)
或者
Optional.orElse?(T other)对比Optional.orElseGet?(Supplier<? extends T> supplier)
或者
log?(System.Logger.Level level, String msg)对比log?(System.Logger.Level level, Supplier<String> msgSupplier)
- @Eugene sounds like an issue that can be solved with code transformation. `logger.method(/*string concatenation*/)` gets compiled (JDK 9+) to *push logger, push arguments*, `invokedynamic` (string concatenation), `invoke… method`. The transformator only has to replace the two invocations with a single `invokedynamic` with a custom bootstrap method that consumes *logger* and *arguments*. The custom bootstrap method only needs to get a handle to the original method and prepend the condition check.