How to avoid tedious null checks on an object
If I have a class that I want to accept an optional logger to log debug information:
public class A {
private Logger logger ;
public A( Logger logger ) {
this.logger = logger ;
}
public A() {
this( null ) ;
}
public void hello() {
logger.debug( "hello" ) ;
}
public void goodbye() {
logger.warn( "goodbye" ) ;
}
}
Is there any way for me to avoid the need for constant null checks?
public void hello() {
if( logger != null ) {
logger.debug( "hello" ) ;
}
}
public void goodbye() {
if( logger != null ) {
logger.warn( "goodbye" ) ;
}
}
I thought maybe if I made a logger wrapper class, that could do the开发者_如何学Go checks for me and then either do nothing, or log the message. But then I would need to wrap each method I would want to use.
I would create Logger
as an interface and implement the real logger and a dummy class that doesn't log anything. This way, you can always just access the logger without any null checks.
All answers basically suggest using Null Object pattern, see:
- http://en.wikipedia.org/wiki/Null_Object_pattern
- Null Object Pattern to avoid Null checks?
2 things:
- always initialize the logger
- (and/or) use a sentinel logger that doesn't to anything at all
Something like this maybe:
private void logDebug(final String str, final Object ... parameters ) {
if (this.logger != null && this.logger.isDebugEnabled()) {
this.logger.debug(
parameters.length > 0
? MessageFormat.format(str, parameters)
: str
);
}
}
private void logInfo(final String str,final Object ... parameters) {
if (this.logger != null && this.logger.isInfoEnabled()) {
this.logger.info(
parameters.length > 0
? MessageFormat.format(str, parameters)
: str
);
}
}
Now you can just call logDebug(str)
or logInfo(str)
, and you can also interpolate the log messages with parameters using MessageFormat.format()
:
logDebug("Called {0} method with parameters {1} and {2}","doStuff",foo,bar);
Sorry if it sounds dumb, but won't making the methods Warn and Debug static solve this ? If you need an instance just create it inside the static methods, or if its a singleton check forr null inside the static methods.
You could set a boolean "enableLogging" to true in your 1-parameter constructor, and to false in your empty constructor. Thus you give more meaning to your checks - and they are faster.
The main problem is you are using null everywhere, which means naturally you need to test for null everywhere. Create a Logger where all methods do nothing and use that instance where appropriate.
精彩评论