在使用String.valueOf()时,由于对该工具方法没有足够的了解,导致有一处代码出现了bug,在这里记录下来自己的采坑经历,出bug的业务代码跟下面代码中的case1和case2很相似。

    1. public static void main(String[] args) {
    2. Map<String, Object> extendMap = buildExtendMap();
    3. //case1
    4. String value1 = String.valueOf(extendMap.get("key1"));
    5. System.out.println(value1);
    6. //case2
    7. String value2 = String.valueOf(extendMap.get("key3"));
    8. System.out.println(value2);
    9. //case3
    10. String value3 = String.valueOf(null);
    11. System.out.println(value3);
    12. //calse 4
    13. String value4 = (String) null;
    14. System.out.println(null == value4);
    15. }
    16. public static Map<String, Object> buildExtendMap() {
    17. Map<String, Object> extendMap = Maps.newHashMap();
    18. extendMap.put("key1", "value1");
    19. extendMap.put("key2", "value2");
    20. return extendMap;
    21. }

    case1不用多说,大家应该都知道会返回”value1”。case2返回的值是”null”,当时就是在这里出的bug,看了源码之后恍然大悟,因为extendMap的value是Object类型,所以String.valueOf()自然而然的就会重载到对应的方法,方法的源码如下:

    1. /**
    2. * Returns the string representation of the {@code Object} argument.
    3. *
    4. * @param obj an {@code Object}.
    5. * @return if the argument is {@code null}, then a string equal to
    6. * {@code "null"}; otherwise, the value of
    7. * {@code obj.toString()} is returned.
    8. * @see java.lang.Object#toString()
    9. */
    10. public static String valueOf(Object obj) {
    11. return (obj == null) ? "null" : obj.toString();
    12. }

    case3抛出空指针的异常,debug发现case3重载到String.value(char[] value)方法。为什么会重载到该方法,首先来看null属于什么类型,属于int\char\long\short\byte\boolean\double\float这八种基本类型吗?显然不是,那null就是对象,String.valueOf()提供了针对下面两种对象的重载,Java编译器会找到一个相近的方法去执行,首选valueOf(char data[])方法。

    1. public static String valueOf(char data[]) {
    2. return new String(data);
    3. }
    4. public static String valueOf(Object obj) {
    5. return (obj == null) ? "null" : obj.toString();
    6. }

    image.png
    null可以转换为任何Java对象类型,所以(String)null也是ok的。