侧边栏壁纸
博主头像
Ivan Zhang

所谓更牛,就是换个罪受

  • 累计撰写 48 篇文章
  • 累计创建 54 个标签
  • 累计收到 6 条评论

目 录CONTENT

文章目录

JDK中的String.valueOf()传null的诡异处理

Ivan Zhang
2022-01-19 / 0 评论 / 0 点赞 / 730 阅读 / 1,937 字
温馨提示:
本文最后更新于 ,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。
有什么问题或观点欢迎评论留言,或者 交流。
如果觉得文章对您有所帮助,可以给博主打赏鼓励一下。
public class TestString {
	public static void main(String[] args) {
		Object obj = null;
		// 输出 "null" 字符串,不是空对象 null,也不是空字符串 ""
		System.out.println(String.valueOf(obj));
		// 抛出空指针异常
		System.out.println(String.valueOf(null));
	}
}

下面来分析分析原因。

第一个的源码实现:

/**
 * 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();
}

源码很简单,如果对象为空,就返回字符串的"null"...不为空就调用toString方法。

第二个和第一个的不同,是 java 对重载的不同处理导致的。
基本类型不能接受 null 入参,所以接受入参的是对象类型,如下两个:
String valueOf(Object obj)
String valueOf(char data[])
这两个都能接受 null 入参,这种情况下,Java 的重载会选取其中更精确的一个,所谓精确就是,重载方法 A 和 B,如果方法 A 的入参是 B 的入参的子集,则 A 比 B 更精确,重载就会选择 A。换成上面这两个就是,char[] 入参的比 object 的更精确,因为 object 包含 char[],所以 String.valueOf(null) 是用 char[] 入参这个重载方法。

看看这个方法的实现:

/**
 * Returns the string representation of the <code>char</code> array
 * argument. The contents of the character array are copied; subsequent
 * modification of the character array does not affect the newly
 * created string.
 *
 * @param   data   a <code>char</code> array.
 * @return  a newly allocated string representing the same sequence of
 *          characters contained in the character array argument.
 */
public static String valueOf(char data[]) {
	return new String(data);
}

直接 new String,再看 new String 的实现:

/**
 * Allocates a new {@code String} so that it represents the sequence of
 * characters currently contained in the character array argument. The
 * contents of the character array are copied; subsequent modification of
 * the character array does not affect the newly created string.
 *
 * @param  value
 *         The initial value of the string
 */
public String(char value[]) {
	this.offset = 0;
	this.count = value.length;
	this.value = StringValue.from(value);
}

第12行,入参为 null 就报 NPE 了。

JDK 中的奇葩实现比较多,大家用的时候养成多看源码实现的好习惯,可以避免踩坑...

参考链接

0

评论区