null的伟大与可怕 之 String字符串 1

null的伟大与可怕 之 String字符串

null的伟大与可怕 之 String字符串 1
http://blog.csdn.net/sunrainamazing/article/details/71591334
null的伟大与可怕 之 String字符串方法2
http://blog.csdn.net/sunrainamazing/article/details/71593030
null的伟大与可怕 之 Optional操作 3
http://blog.csdn.net/sunrainamazing/article/details/71596437

基本类型会被自动初始化为
byte short int long –> 0
float double –>0.0
boolean –> false
char –> ” 转换成int 为 0 空字符
引用类型则统一为 null ,但是对象引用会被初始化为 null。
当尝试调用null对象的方法,就会抛出空指针异常。
但是 通常,print 一个 null 对象而不会抛出异常,且输出的值为 null。
那么为什么可以输出一个 null 对象不会抛出异常且值为null?
是不是null对象的值就是null呢?

package sun.rain.amazing.strnull;

/**
 * Created by sunRainAmazing on SUN_RAIN_AMAZING
 * @author sunRainAmazing
 */

import sun.rain.amazing.bean.User;
import org.junit.Test;

public class StringNull {

    /**
     * 测试String 类型的 null对象
     */
    @Test
    public void testStringNull(){
        String str = null;
        System.out.println(str);
    }
    /*
 没有抛出异常,而是打印了null。
 显然问题的线索在于print函数的源码中。我们找到print的源码:

             public void print(String s) {
                    if (s == null) {
                        s = "null";
                    }
                    write(s);
                }

看到源码才发现原来就只是加了一句判断而已,简单而又粗暴,仅赋值为 null。
*/




    /**
     * 测试非String 类型的 null对象
     */
    @Test
    public void testNoStringNull1(){
        Object obj = null;
        System.out.println(obj);
    }
    /**
       我们再去看看print的源码:
         public void print(Object obj) {
            write(String.valueOf(obj));
         }
     有点不一样的了,看来秘密藏在valueOf里面。
         public static String valueOf(Object obj) {
            return (obj == null) ? "null" : obj.toString();
         }
     看到这里,我们终于发现了打印 null 对象不会抛出异常的秘密。

     print方法对 String 对象和非 String 对象分开进行处理。
     【String 对象】:直接判断是否为null,如果为 null给null对象赋值为"null"。
     【非 String 对象】:通过调用String.valueOf方法,
        如果是 null 对象,就返回"null",否则调用对象的toString方法。

     通过上面的处理,可以保证打印 null 对象不会出错。
     */


    /*
    ===================================
       null 对象与字符串拼接会得到什么结果?
         String s = null;
         s = s + " is not null ";
         System.out.print(s);
    ===================================

    编译器对字符串相加会进行优化,首先实例化一个StringBuilder,
    然后把相加的字符串按顺序append,
    最后调用toString返回一个String对象。

    String s = "a" + "b";
    //等价于
        StringBuilder sb = new StringBuilder();
        sb.append("a");
        sb.append("b");
        String s = sb.toString();



    再回到我们的问题,现在知道秘密在StringBuilder.append函数的源码中。
    //针对 String 对象
    public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }

    //针对非 String 对象
    public AbstractStringBuilder append(Object obj) {
        return append(String.valueOf(obj));
    }

    //针对 null对象
    private AbstractStringBuilder appendNull() {
        int c = count;
        ensureCapacityInternal(c + 4);
        final char[] value = this.value;
        value[c++] = 'n';
        value[c++] = 'u';
        value[c++] = 'l';
        value[c++] = 'l';
        count = c;
        return this;
    }

    现在我们恍然大悟,append函数如果判断对象为 null,
      就会调用appendNull,填充"null"。
     */


    @Test
    public void testAppend(){
        StringBuffer sBuffer = new StringBuffer("ad");
        sBuffer.append("D_");
        sBuffer.append(new User());

        System.out.println(sBuffer.toString());
        //sun.rain.amazing.bean.User@7aec35a

    }



}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值