已阅读5页,还剩1页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
前言最近在读Thinking in Java,看到这样一段话:Primitives that are fields in a class are automatically initialized to zero, as noted in the Everything Is an Object chapter. But the object references are initialized to null, and if you try to call methods for any of them, youll get an exception-a runtime error. Conveniently, you can still print a null reference without throwing an exception.大意是:原生类型会被自动初始化为 0,但是对象引用会被初始化为 null,如果你尝试调用该对象的方法,就会抛出空指针异常。通常,你可以打印一个 null 对象而不会抛出异常。第一句相信大家都会容易理解,这是类型初始化的基础知识,但是第二句就让我很疑惑:为什么打印一个 null 对象不会抛出异常?带着这个疑问,我开始了解惑之旅。下面我将详细阐述我解决这个问题的思路,并且深入 JDK 源码找到问题的答案。解决问题的过程可以发现,其实这个问题有几种情况,所以我们分类讨论各种情况,看最后能不能得到答案。首先,我们把这个问题分解为三个小问题,逐一解决。第一个问题直接打印 null 的 String 对象,会得到什么结果?String s = null;System.out.print(s);运行的结果是null果然如书上说的没有抛出异常,而是打印了null。显然问题的线索在于print函数的源码中。我们找到print的源码:public void print(String s) if (s = null) s = null; write(s);看到源码才发现原来就只是加了一句判断而已,简单粗暴,可能你对 JDK 的简单实现有点失望了。放心,第一个问题只是开胃菜而已,大餐还在后面。第二个问题打印一个 null 的非 String 对象,例如说 Integer:Integer i = null;System.out.print(i);运行的结果不出意料:null我们再去看看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 对象分开进行处理。1. String 对象:直接判断是否为 null,如果为 null 给 null 对象赋值为null。2. 非 String 对象:通过调用String.valueOf方法,如果是 null 对象,就返回null,否则调用对象的toString方法。通过上面的处理,可以保证打印 null 对象不会出错。到这里,本文就应该结束了。什么?说好的大餐呢?上面还不够塞牙缝呢。开玩笑啦。下面我们来探讨第三个问题。第三个问题(隐藏的大餐)null 对象与字符串拼接会得到什么结果?String s = null;s = s + !;System.out.print(s);结果可能你也猜到了:null!为什么呢?跟踪代码运行可以发现,这回跟print没有什么关系。但是上面的代码就调用了print函数,不是它会是谁呢?+的嫌疑最大,但是+又不是函数,我们怎么看到它的源代码?这种情况,唯一的解释就是编译器动了手脚,天网恢恢,疏而不漏,找不到源代码,我们可以去看看编译器生成的字节码。L0 LINENUMBER 27 L0 ACONST_NULL ASTORE 1L1 LINENUMBER 28 L1 NEW java/lang/StringBuilder DUP INVOKESPECIAL java/lang/StringBuilder. ()V ALOAD 1 INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder; LDC ! INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder; INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String; ASTORE 1L2 LINENUMBER 29 L2 GETSTATIC java/lang/System.out : Ljava/io/PrintStream; ALOAD 1 INVOKEVIRTUAL java/io/PrintStream.print (Ljava/lang/String;)V看了上面的字节码是不是一头雾水?这里我们就要扯开话题,来侃侃+字符串拼接的原理了。编译器对字符串相加会进行优化,首先实例化一个StringBuilder,然后把相加的字符串按顺序append,最后调用toString返回一个String对象。不信你们看看上面的字节码是不是出现了StringBuilder。详细的解释参考这篇文章Java细节:字符串的拼接。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);private AbstractStringBuilder appendNull() int c = count; ensureCapacityInternal(c + 4); final char value = this.value; valuec+ = n; valuec+ = u; valuec+ = l; valuec+ = l; count = c; return this;现在
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 溯民族精神之源 辟民族复兴之路
- 高校教学评估与质量建设
- 重症医学科(ICU)各类型气管插管护理规范
- 精神病症状学基础讲座
- 感染科医院感染监测与管理措施
- 2025药品生产厂家质量负责人聘用合同范本
- 2025船舶运输煤炭合同范本
- 2025合同模板:广告合作协议
- 2025农产品销售合同
- 2025房地产项目代理合同土地
- 非遗申报范本
- (完整版)10G409预应力管桩图集
- 《思想道德与法治》课件第四章明确价值要求践行价值准则第三节积极践行社会主义核心价值观
- 富氧节能环保燃烧技术介绍
- PCBA来料检验标准
- NB/T 10726-2021煤矿膏体充填管道输送工艺要求
- GB/T 3821-2015中小功率内燃机清洁度限值和测定方法
- GB/T 29529-2013泵的噪声测量与评价方法
- 危害识别与风险评价
- 防诈骗专题教育
- 五年级上册数学课件-回顾整理-总复习|青岛版(五四制) (共19张PPT)
评论
0/150
提交评论