java null返回空对象_java 中 if (someobject != null) 检查对象是否为空的问题

通常我们在 public Set 时,如果没有特殊说明,返回的set 是不能为 null 的。所以严格的说,返回是否为空,我们需要判断,因为可能会出现问题。

先我们来看下面代码,对于这样的对象为空的检查:

if (someobject != null) {

someobject.doCalc();

}

为了避免空指针异常,看起来也没什么不妥。不过代码里面一片一片的对象是否为空的判断,实在难看。

对象是否为空的契约

通常我们在定义API的时候,是遵循一些规矩的,这些规矩可以叫做规约,比如这样的接口:

public Set getCollections();

通常情况下,或者说没有特殊说明的情况下,返回的set是不能为null的,如果没有元素,应当是一个EmptySet才对。接口上下游都遵守这样的规约了,那么一些防御性代码就可以省掉。所以严格来说,返回是否为空,应当加入到API的文档中去,在返回为空时,需要声明其特殊意义。对象为空,经常能够表达特殊含义:

public void updateUser(User user);

比如这样的方法,要更新user的信息,user有一个属性age,类型Integer,当它为空的时候,表示忽略该属性,不更新。如果使用原语类型int就需要使用某种特殊值了,没有Integer来得自然。

其他语言的改进

在Groovy中,使用问号这样一个语法糖,使得代码判空的逻辑得到最简化:

def streetName = user?.address?.street

上面的代码中,如果user为空,是不会访问它的address成员的,如果address为空,则是不会访问street的。

在Objective C中,方法调用变成了消息传递机制,在往nil传递消息的时候,除了返回0并没有什么副作用发生。关于“空”,在Objective C当中有这样四种:

2fd356fad4b8085e9820b19ccba8dfce.png

NULL来自于C语言的空指针;nil是一个指向空的对象;Nil和nil类似,只不过它是一个指向空的类;NSNull是用来解决集合元素没法放空元素的问题的,它就相当于空元素的一个包装,在集合中表示一个空元素。

Scala中有一个Option抽象类,它是强类型的,即Option[T],这个类型一旦被定义就不能改变。它下面有两个子类,Some和None,None是一个表示空的单例对象,而Some存放的是实际结果:

def show(x: Option[String]) = x match {

case Some(s) => s

case None => "?"

}

编译期间发现对象为空的问题

在JSR 305: Annotations for Software Defect Detection中,最初来自于FindBug和IntelliJ的灵感,说白了就是@NonNull和@CheckForNull这两个注解:

如果有这样的方法定义:

void someMethod(@NotNull someParameter) { }

那么,在调用的时候,这样的代码会直接编译失败的:

someMethod(null);

反之,定义这样的方法:

@Nullable iWantToDestroyEverything() { return null; }

那么这样未经检查的方法调用也会在编译期间失败:

1

iWantToDestroyEverything().something();

也就是说,在编译时间就找出潜在的NPE问题。

对象为空的检查

不需要自己写防御性质的判断语句来处理空对象了。比如JDK7的Objects对象:

this.child = Objects.requireNonNull(child, "it is empty");

这会在对象不为空时完成赋值语句,对象为空时抛出消息为“it is empty”的异常。

Jarkata Commons的API也提供了检查对象是否为空的方法;或者,你可以用Java原生的assert关键字。

NPE也受欢迎

比如这样的代码:

public Photo getGirlfriendPhoto() {

try {

return appContext.getPhotoDataSource().getPhotoByName(me.getGirlfriend().getName());

} catch (NullPointerException e) {

return null;

}

}

如果要避免NPE,就可能会写成类似这样的代码:

public Photo getGirlfriendPhoto() {

if(appContext != null) {

if(appContext.getPhotoDataSource() != null) {

if(me != null) {

if(me.getGirlfriend() != null) {

if(me.getGirlfriend().getName() != null){

// finally we are arrived

return appContext.getPhotoDataSource().getPhotoByName(me.getGirlfriend().getName());

}

}

}

}

}

return null;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值