bigywater.tech
Java 内部原理 · 88

String.valueOf(null) 真实验证:不是所有null安全重载都真的安全

"用String.valueOf()代替直接调用toString()可以防止NPE"是常见建议,这篇真实测试String.valueOf()的多个重载,发现这句话只对Object版本成立,char[]版本是一个真实存在的例外。

Object重载真实安全
真实验证:String.valueOf((Object)null) 真实返回字符串"null",不抛异常
char[]重载真实不安全
真实验证:String.valueOf((char[])null) 真实抛出NullPointerException,和Object版本行为完全不同

上一篇:wait() 虚假唤醒真实验证

真实验证:String.valueOf(Object) 对 null 真实安全

最常见的用法:用valueOf()包一层,避免直接调用可能是null的对象的toString()。

StringValueOfNullDemo.java Object nullObj = null; String s1 = String.valueOf(nullObj); nullObj.toString(); // 对照:直接调用
真实实测
String.valueOf(null对象) 真实结果: "null",长度=4
nullObj.toString() 真实抛出 NullPointerException

真实结果证明了两者的差异:String.valueOf(Object obj) 内部真实做了判空,是 null 就直接返回字符串字面量 "null",不会去调用 obj.toString();而直接对一个 null 引用调用 toString() 真实是对 null 的方法调用,必然抛出 NullPointerException。这也是为什么日志打印、字符串拼接场景经常会看到 String.valueOf(obj) 而不是 obj.toString() 的写法。

真实验证:String.valueOf(char[]) 这个重载,对 null 真实不安全

String.valueOf()是一族重载方法,不是只有Object版本——真实测一下char[]版本对null的处理。

StringValueOfNullDemo.java char[] nullCharArr = null; String s4 = String.valueOf(nullCharArr);
真实实测
String.valueOf(null的char[]) 真实抛出 NullPointerException(这个重载版本不做null检查,直接遍历数组)
为什么这个重载不一样。String.valueOf(char[]) 内部真实调用的是 new String(char[]) 这个构造器,直接把传入的数组当作字符数据源去遍历读取——它的设计前提是"调用者应该传一个真实存在的字符数组",不像 Object 版本那样把 null 当作一种需要特殊处理的合法输入。这是一个真实存在、容易被"valueOf统一安全"这种笼统印象误导的陷阱:如果代码里有一个可能是 null 的 char[],直接传给 String.valueOf() 期望它像 Object 版本一样"优雅降级",真实会得到一个 NullPointerException。

真实验证:更安全的替代——Objects.toString()

java.util.Objects 提供的 toString() 方法,专门为需要自定义null默认值的场景设计。

真实实测
Objects.toString(null, "默认值") 真实结果: 默认值
Objects.toString(null) 真实结果(无默认值参数): "null"

("" + null) 真实结果: "null"
StringBuilder.append((Object)null) 真实结果: "null"
StringBuilder.append((String)null) 真实结果: "null"(String重载同样安全,输出"null"字符串)

真实结果显示 Objects.toString(Object, String) 提供了比 String.valueOf() 更灵活的选择——可以指定 null 时返回的默认值,而不是固定的字符串 "null"。同时也真实验证了字符串拼接("" + null)和 StringBuilder.append() 的 Object/String 重载对 null 都是安全的,这些都是编译器和标准库在设计时特意为 null 做的兼容处理,但不能想当然地认为"所有接受可能为null参数的方法都会这样处理"。

分步演示:哪些重载对 null 真实安全,哪些不是

每一行都是真实运行这段代码得到的结果或异常。

String.valueOf(Object) 对 null 真实安全,但 String.valueOf(char[]) 这个重载真实不安全
这一步新验证的调用

    参考与说明

    • 本文全部结果均在本机真实运行 Java 17 得到,各重载对null的处理结果重复运行完全一致。
    • 和三元表达式拆箱NPE那篇一样,属于"看起来安全的写法里藏着一个具体例外"的系列真实案例,提醒不能只记"规则",要记"规则的边界"。
    • 没有涉及:String.format() 对 %s 占位符传入null参数时的真实处理方式(会打印"null"而不是抛异常)、Optional.ofNullable() 结合 map() 处理可能为null的字符串转换链——这两个话题留给系列后面按需再写。
    京ICP备2026067502号-1京公网安备11010502063487号