I would like to create a log message which contains the values of at least one local variable. To benefit form lazy evaluation I would like to pass a Supplier<String>
to the logging frame work.
private void doSomething(Object a, Object b){
var myLocalVar = deriveValFrom(a);
if (null == myLocalVar){
myLocalVar = deriveValFrom(b);
}
LOG.debug(() -> String.format("settled on value %s", myLocalVar));
}
The code above does not compile, since myLocalVar
is neither final nor effectively final.
current ideas As the answers to this question show, I might define a temp variable and thus bloat the code.
Otherwise I could implement a private method like
private void logToDebug(String formatStr, Object p0, Objects... objs){
LOG.debug(()->String.format(formatStr, p0, objs));
}
Which makes the compiler stop complaining but adds 'off-topic' code to the class.
actual Q Is there a better way to achieve lazy evaluation and concise code?
relevant info
While logging is done under the hood by log4j I have to work through a custom facade which I may extend (for instance with the debug(String formatStr, p0, ...)
-Methods) but I would like to keep the extension to a minimum.
CodePudding user response:
I'd split logic into two methods:
private void doSomething(Object a, Object b){
final var myLocalVar = deriveValFrom(a);
if (myLocalVar != null)
return myLocalVar;
return deriveValFrom(b);
}
private void doSomethingAndLog(Object a, Object b){
final var myLocalVar = doSomething(a, b);
LOG.debug(() -> String.format("settled on value %s", myLocalVar));
}
CodePudding user response:
It depends a bit on what part of the exection you want to be lazy. A final constant would normally use an assignless expression. Optional is very suitable for that.
But you can do all in the log call.
private void doSomething(Object a, Object b) {
final var myLocalVar = Optional.ofNullable(deriveValFrom(a))
.orElseGet(() -> deriveValFrom(b)));
LOG.debug(() -> "settled on value %s".formatted(
Optional.ofNullable(deriveValFrom(a))
.orElseGet(() -> deriveValFrom(b)));
}