2016年8月10日 星期三

Select between valueOf() and toString() while converting Objects to String

While we are doing development, we need to convert an Object into String for passing into a method as an argument frequently.

Let’s take a look of code snippet below as an example:
     public void convertAndLog(String msg){
         System.out.println(msg);
     }

If your application logic must have to call the above method, you need to guarantee /convert the argument as String before passing it to the convertAndLog(..). In usual, 2 methods would come into our mind immediately:
-              String.valueOf(argument)
-              argument.toString()

Which one of the above would be more preferred?
I would suggest to use String.valueOf(argument)

If you study the API of String class, you will find that String.valueOf(argument) actually is capable of different types of arguments no matter primitive or Object.
i.e.
String.valueOf(primitive)
String.valueOf(Object)

In addition, String.valueOf(Object) has already cater for Null value. If we take a look of the API of String.valueOf(Object), it is as below:
    /**
     * Returns the string representation of the <code>Object</code> argument.
     *
     * @param   obj   an <code>Object</code>.
     * @return  if the argument is <code>null</code>, then a string equal to
     *          <code>"null"</code>; otherwise, the value of
     *          <code>obj.toString()</code> is returned.
     * @see     java.lang.Object#toString()
     */
    public static String valueOf(Object obj) {
        return (obj == null) ? "null" : obj.toString();
    }

Code snippet of Object.toString():
    /**
     * Returns a string representation of the object. In general, the
     * {@code toString} method returns a string that
     * "textually represents" this object. The result should
     * be a concise but informative representation that is easy for a
     * person to read.
     * It is recommended that all subclasses override this method.
     * <p>
     * The {@code toString} method for class {@code Object}
     * returns a string consisting of the name of the class of which the
     * object is an instance, the at-sign character `{@code @}', and
     * the unsigned hexadecimal representation of the hash code of the
     * object. In other words, this method returns a string equal to the
     * value of:
     * <blockquote>
     * <pre>
     * getClass().getName() + '@' + Integer.toHexString(hashCode())
     * </pre></blockquote>
     *
     * @return  a string representation of the object.
     */
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }


From the above API method of String.valueOf( Object ), we can know that if the passed in argument is Null, it would return a String value of “null”. However, if the object is null and we call object.toString() directly, it will throws NullPointerException which should definitely not a preferred case for most systems.


Conclusion

So, String.valueOf() is definitely the preferred method while it has already helped us to cater the Null value and keep the code neat.

In general, String.valueOf() is over the object.toString() with the following points:
1.      It avoids NullPointerException being throws
2.      It helps to keep code neat while the Null value check has been implemented inside
3.      String class API has already cater for conversion from both primitives and Objects

At last, let’s take an example of the difference while encountering Null value along with the above code snippet:
public class Parent {

     static class Child
     {
         private String name;
        
         public String getName() {
              return name;
         }
         public void setName(String name) {
              this.name = name;
         }
     }
    
     /*
      * We log the msg to console here
      */
     public void convertAndLog(String msg){
         System.out.println(msg);
     }
    
     public static void main(String[] args){
        
         Parent p = new Parent();
         Parent.Child c = null;
        
         /**
          * It would check for null value and convert as String value of "null"
          */
         p.convertAndLog("String.valueOf(c) : " + String.valueOf(c)); 
        
         /**
          * It would throws NullPointerException if Child is null
          */
         p.convertAndLog("c.toString() : " + c.toString()); 
     }
}

Result:
String.valueOf(c) : null
Exception in thread "main" java.lang.NullPointerException
     at Parent.main(Parent.java:36)


The result reveals that NullPointerException is encountered while calling c.toString() with c is Null.


沒有留言:

張貼留言