问题
I've got a method
like this:
private String getOrderListAsString() {
StringBuilder str = new StringBuilder();
str.append("Sell list:");
for (Order o : sellOrderList) {
str.append("\nSale: ").append(o);
}
str.append("Buy list:");
for (Order o : buyOrderList) {
str.append("\nBuy: ").append(o);
}
return str.toString();
}
It's called with logging parameterization like so: We're using java.util.logging as a logger.
logger.log(Level.INFO, "{0}", getOrderListAsString());
The problem is that the string concatination is still being done even if the logger level is Level.OFF
.
To get around this we've added an if
statement at the start of the method:
// Declaration:
boolean shouldLog = DebugWriter.getInstance().getLogger().getLevel() != Level.OFF;
// Usage in function:
if(!shouldLog) return null;
But it feels like this could be done in a more clever way. Thanks in advance!
回答1:
If you are using Java 8+, then java.util.Logger has an overload of the log
method that takes a Supplier
public void log(Level level,
Supplier<String> msgSupplier)
Now, you can make the string generated from a supplier like
logger.log(Level.INFO, () -> getOrderListAsString());
or, using method reference
logger.log(Level.INFO, this::getOrderListAsString);
Javadoc
回答2:
java.util.logging has overloads that take Supplier<String>
but not in combination with a format string. So you can use it like this:
logger.info(() -> getOrderListAsString());
Or create a new abstraction OrderList
that has a toString()
method. Then you can simply pass it as a parameter, and the logger will invoke toString()
, if needed.
回答3:
Same spirit as Eran's answer, but just wrap the argument rather than change the log implementation
public class LazyToString
{
private final Supplier<String> stringSupplier;
public LazyToString(Supplier<String> stringSupplier)
{
this.stringSupplier = stringSupplier;
}
@Override
public String toString()
{
return stringSupplier.get();
}
}
Sample usage:
log.info("Something happened {}", new LazyToString(this::getOrderListAsString));
If that's too verbose, you can create a static method call which creates the object rather than using new, maybe would look something like this
log.info("Something happened {}", lazy(this::getOrderListAsString));
来源:https://stackoverflow.com/questions/59284520/java-string-parameterization-performace-loss-on-indirect-tostring-methods