开发者

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:

  1. always initialize the logger
  2. (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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜