String.valueOf()传入null值的问题

今天在项目中遇到了一个String.valueOf()中传入null值的问题,刚开始颇为不解,后来经过百度和查看源码才得以解惑,记录下来,以防以后再次踩坑。上代码:

public class MyTest {
    @Test
    public void test(){
        String str = String.valueOf(null);
        System.out.println(str);
    @Test
    public void test1(){
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("id", null);
        String str = String.valueOf(map.get("id"));
        System.out.println(str);

测试输出:
test()方法:

java.lang.NullPointerException
	at java.lang.String.<init>(String.java:166)
	at java.lang.String.valueOf(String.java:3008)
	at cloudboy.MyTest.test(MyTest.java:11)

test1()方法:

Process finished with exit code 0

因此很困惑啊,明明两个方法中传入的都是null值,为何一个报空指针异常,一个却是正常的。点击方法进入源码后才发现,它们进入了不同的方法:

 String str = String.valueOf(null);
 public static String valueOf(char data[]) {
        return new String(data);
public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
String str = String.valueOf(map.get("id"));
 public static String valueOf(Object obj) {
        return (obj == null) ? "null" : obj.toString();

原来,valueof方法被重载多次,其中String.valueof(null)进入了valueof(char[] data)方法,valueof(char[] data)方法直接进入String构造器,内部会获取char[]的length,因此返回空指针异常。String.valueOf(map.get(“id”))却进入了valueOf(Object obj)方法,参数为null时,返回了一个字符串“null”,所以出现了不同的结果。

那重载方法是如何被选择的呢?
多个重载方法均能匹配的条件下,优先会选择精度高的那个,或者说范围小的那个,那上面的问题就明朗了,char[]和object均能匹配null值,而char[]是继承自object的(java中数组也是一种特殊的object),因此string。valueOf(null)优先选择精度高的char[],而String.valueOf(map.get(“id”))中map的v值已经声明为了object,所以它只能进入valueOf(Object obj)方法。

总结:java编译器在选择重载方法时,如果重载方法参数个数一致,且具备多个重载方法可以匹配到所传递的参数,此时,会优先选择精度相对较高的,即java继承树种树的深度较深的那个。

补充一下常见的一些考题:
例子1:

public class TestNull {
    public static void main(String[] args) {
        test(null);   //此处将返回arraylist,因为list同arraylist存在继承或实现的上下级关系
    static void test(List list) {
        System.out.println("list");
    static void test(ArrayList list) {
        System.out.println("arraylist");

结果:输出arraylist

public class TestNull {
    public static void main(String[] args) {
        test(null);   //本行会编译报错
    static void test(String str) {
        System.out.println("string");
    static void test(Integer num) {   //如果修改为int,则编译通过
        System.out.println("integer");

结果:编译失败
因为构造函数是编译时期确定的,代码将无法通过编译,因为String同Integer不存在任何关系,他们都继承自Object,他们的公共父类是object(String和String[]也是一样的道理),此时null值不知道该传入那个方法,因此无法通过编译,将报错。

Android 获取经度 纬度 位置信息,在Android系统的手机上运行后,会显示出纬度和经度信息,具体的方法请参见以下代码:   //方法:返回查询条件   public Criteria getCriteria(){    Criteria c = new Criteria();    c.setAccuracy(Criteria.ACCURACY_COARSE); //设置查询精度    c.setSpeedRequired(false);//设置是否要求速度    c.setCostAllowed(false);//设置是否允许产生费用    c.setBearingRequired(false);//设置是否需要得到方向    c.setAltitudeRequired(false);//设置是否需要得到海拔高度    c.setPowerRequirement(Criteria.POWER_LOW);//设置允许的电池消耗级别    return c;//返回查询条件   }   //方法:更新EditText中显示的内容   public void updateView(Location newLocation){   if(newLocation !=null){//判断是否为空    et.setText("您现在的位置是\n纬度:");    et.append(String.valueOf(newLocation.getLatitude())); //获得纬度    et.append("\n经度:");    et.append(String.valueOf(newLocation.getLongitude()));//获得精度   }   else{ //如果传入的Location对象为空则清空EditText    et.getEditableText().clear();//清空EditText对象   } System.out.println(String.valueOf(aa)); 如上,用String.valueOf() 可以避免空指针,但是会返回 “null”, 这在有时候并不是我想要的结果。 替代方法: Object aa = null; String ss = Objects.toString(aa, null); 用 Objects.toStri... 背景:线上发现当某个字段返回是null时候,保到数据库的是字符串"null",正常需要保的应该是null。 看代码发现代码里用了一个方法 String a = String.valueOf(Object obj),然后返回a,问题String.valuOf(Object obj)这里。 JDK1.8 String.valueOf(Object obj)源码: public static ... 最近出现一个莫名奇妙的问题: 数据库中储了 "null" 字符串…… 用的 SpringCloud 远程调用接口, 传参为 null, 接到的参数: “null”,导致上文的bug. 当时只能单独写了一个方法处理 “null”,对其进行了转换。 原因分析: Java String 类源码: * Returns the string representation of the {@code Object} argument. * @par 一、String.valueOf()当传入的参数为一个引用且该引用为 null 时,方法返回字符串“null” 简言之,如果对象为 null 就返回字符串的“null”,不为空就调用 toString 方法。此时若用StringUtils.isBlank()这类方法判断时将返回 true。该方法的源码如下(jdk1.8.0_131中String的部分源码): 特别注意: valueOf() 可能会返回“null”字符串,不能用 StringUtils.isEmpty() 或 isBlank() 来简单地判 因为String同Integer不在任何关系,它们都继承自Object,公共父类是Object(StringString[]同理),此时null不知道该传入哪一个方法,因此无法通过编译,直接报错。总结:java编译器在选择继承重载方法时,如果请求方法参数个数一致,且具备多个重载方法可以匹配到所传递的参数,此时,会优先选择精度相对较高的,即java继承树中树的深度较深的那个。问题:明明两个方法中传入的都是null,为何一个报空指针异常,一个却是正常的。问题:重载方法是如何被选择的? 笔者在最近的开发中解析Excel,遇到了一个奇怪的bug,明明字段解析出来的结果是null,postman中显示为null,但是还是通过了非空校验。 最终debug的时候,看到了这个 看了下源码: 原来String.valueOf()是将为null时,将一个“null”的字符串传进String变量中。忘记了这一点,结果就是结果看到是null,但是还是通过了非空校验。 这次的问题总结出两点问题, 第一,不要再忘记String.valueOf()是把为null时把"null"赋给变量。 第二,非空校验要在赋 String.valueOf(map.get("key"))的返回为“null”字符串?今天认真的学习一下。 1、看了一下StringvalueOf()的方法,     String valueOf(Object obj)         String valueOf(char data[])       String valueOf(boolean b)      String java中除基本类型外,参数都是引用传递。但是,有一个例外,就是当实参为null时,其实,它依然是一个传递。 “年轻时,我没受过多少系统教育,但什么书都读。读得最多的是诗,包括烂诗,我坚信烂诗早晚会让我邂逅好诗。” by. 马尔克斯 引用:https://www.cnblogs.com/jzsg/p/11308627.html 因为对象传递的是地址,而null没有地址,所以也就没有什么可以传递,所以为传 匿名用户1级2019-03-14 回答publicstaticvoidmain(String[]args){/***1、Java定义一个一维数组,并给每个元素赋为数组下标的,并显示*/int[]arr=newint[10];for(inti=0;iarr[i]=i;System.out.println(i+","+arr[i]);}}publicst... 1、toString(),可能会抛空指针异常 在这种使用方法中,因为java.lang.Object类里已有public方法.toString(),所以java对象都可以调用此方法。但在使用时要注意,必须保证object不是null,否则将抛出NullPointerException异常。采用这种方法时,通常派生类会覆盖Object里的toString()方法。 2、String.valueOf(),推荐使用,返回字符串“nullString.valueOf()方法是小编推荐使用的,因为它不会出