java语言应用中null的处理解析

在调用某个方式,接收返回值时,要先判断返回值是否为null,然后才能继续使用返回值的某个方法,这种情况下,你是否非常希望像写jQuery代码一样的书写java代码?而且不用担心空指针问题么?在个人做过与接触过的系统中,个人感觉一半左右的bug问题,都是由于各种**"空指针"**引起的,如何有效的避免这类问题,提高代码质量,结合网上查询的内容与思考,整理如下.

##值类型与引用类型##

在java世界上,存在两种数据类型:

  1. 基本类型(4类8种):

    1.1 布尔型:boolean(默认值false)

    1.2 字符型:char(默认值0)

    1.3 整数型:byte,short,int,long(默认值为0)

    1.4 浮点数型:float,double(默认值为0.0)

  2. 引用类型:所有非基本类型的都为引用类型,所有引用类型的默认值为null.

##什么是null##

在java中,null是一个关键词,代表不确定的对象,可以将null赋值给引用类型,但是不可以赋值给基本数据类型,比如:

<pre> <code> int a = null;//错误的 Object obj = null;//正确 Integer b = null;//正确,因为Integer是int的包装类,是引用类型,不是基本类型 </code> </pre>

将1个对象赋值为null,主要有两个目的:

  1. 实现对象的延迟初始化:

    在这种情况下,主要是由于创建1个对象需要很大的开销,只在需要调用该对象时才初始化,但是这种模式也是慎用,参见<<Effective Java>>的第71条.

  2. 释放内存,等待垃圾回收器回收该对象

    当引用对象为null时,垃圾回收器运行时,将会销毁该对象.

##null与Object对象##

null不是对象,也不是Object的实例,验证代码如下:

<pre> <code> public class Main{ public static void main(String[] args){ if(null instanceof java.lang.Object){ System.out.println("null是java.lang.Object的类型");//不会输出 }else{ System.out.println("null不是java.lang.Object的类型");//会输出该结果 } } } </code> </pre>

##object==null与null==object的区别##

在判断1个对象是否为null时,可以有这两种写法,这两种写法一样么?

看下边的代码:

<pre> <code> Object obj = null; if(obj==null){ System.out.println("test obj==null"); } if(null==obj){ System.out.println("test null==obj"); } </code> </pre>

就测试结果来说,两种写法是一样的.

但是很多人会选择采用第2种写法,网上有说法是为了防止出现object=null这种的赋值错误.

个人见识到此为止,推荐第2种写法.

##String与null##

先看一段代码:

<pre> <code> @Test public void testStringWithNull(){ String s1 = null,s2=null,s3="test"; System.out.println(s1+s2+s3); } </code> </pre>

运行后,可以看到输出结果前边多了两个null.显然,在做String处理时,一定要考虑到null的情况.

##容器(集合)类与null##

有一些容器(集合)支持null的存储,如

  1. List可以存放多个null元素
  2. Map的key和value都可以存放null 所以在使用这些容器(集合)时,一定要注意存放元素为null的判断.

##API接口返回值的处理原则(返回空对象,返回null,还是抛异常?)##

API接口的返回值遵循以下原则:

  1. 返回值不要返回Null,可以返回空的对象或空的集合

  2. 如果方法校验不通过,无法返回结果对象,可以抛出异常,而不是返回null,并在方法签名中注明抛出异常的原因等

##Null Object Pattern##

Null Object模式详细说明可以参考wiki.

我觉得这里http://segmentfault.com/q/1010000000114775说的挺好.

有一个NullObject与原有业务对象实现相同的接口(或继承同一个父类),让客户端调用时可以无感知(也不必判定null)

摘一张图来说明一下:

空对象模式

其中,RealObject是期望得到的结果,但是如果执行过程中出现错误等,将返回NullObejct对象,而不是null,从而规避"空指针"异常等问题

采用这种方式,可以非常好的实现链式编程,像jQuery一样的代码书写形式.

这种模式的实现可以参考json解析框架:Jackson.

使用Optional类,我们可以对文章开头的代码处理如下:

##Java8 optional##

Java8为了解决空指针对应的一些问题,引入了一个新的Optional类,Optional类的javadoc描述为:

这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

具体的用法可以参考java8 optional深度解析

##思考##

代码优化之路,代码应该怎么写?

扩展阅读:

  1. 10个Java编码中微妙的最佳实践

  2. wiki知识中的Null Object Pattern

  3. java8 optional深度解析

  4. 魔鬼在细节中

参考文档:

  1. wiki知识中的Null Object Pattern

  2. java如不想每次都判空 if

  3. java中Null的学问剖析

  4. 10个Java编码中微妙的最佳实践

  5. 深入java关键字null

  6. 设计模式:空对象模式

  7. 魔鬼在细节中

转载于:https://my.oschina.net/itwarcraft/blog/343175