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

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

if (someobject != null) {
    someobject.doCalc();
}

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

对象是否为空的契约

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

public Set<String> 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当中有这样四种:

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;
}

时间: 2024-08-24 15:28:52

java 中 if (someobject != null) 检查对象是否为空的问题的相关文章

java中getA( ).getB( )意思就是 对象.对象那结果是什么

问题描述 java中getA( ).getB( )意思就是 对象.对象那结果是什么 java中getA( ).getB( )意思就是 对象.对象那结果是什么 结果还是一个对象么, 是不是子对象和父对象的意思呢 java没有这样的概念吧,应该如何理解呢 解决方案 这个要看 getA( ) 和 getB( ) 的具体实现,不能依赖于函数名来判断功能. 解决方案二: public class T2 { public static void main(String[] args) { new T2().

Java中Json字符串直接转换为对象的方法(包括多层List集合)_java

使用到的类:net.sf.json.JSONObject  使用JSON时,除了要导入JSON网站上面下载的json-lib-2.2-jdk15.jar包之外,还必须有其它几个依赖包:commons-beanutils.jar,commons-httpclient.jar,commons-lang.jar,ezmorph.jar,morph-1.0.1.jar 下面是例子代码: // JSON转换 JSONObject jsonObj = JSONObject.fromObject(jsonSt

工厂模式-java中工厂实例就是工厂对象对吗,和普通实例普通对象有什么区别

问题描述 java中工厂实例就是工厂对象对吗,和普通实例普通对象有什么区别 java中工厂实例就是工厂对象对吗,和普通实例普通对象有什么区别 解决方案 工厂实例就是这个工厂类的一个对象,跟普通实例对象没有什么区别的. 主要就是这个工厂实例的作用就是创建某种类型的对象的.即生产什么的工厂.

数据库-java中什么类,什么对象,什么方法,什么语句读取sql表文件的数据的

问题描述 java中什么类,什么对象,什么方法,什么语句读取sql表文件的数据的 java中什么类,什么对象,什么方法,什么语句读取sql表文件的数据的 解决方案 Statement或者preparedStatement类对应的实体对象,使用executeUpdate方法执行sql语句的查询操作.executeUpdate方法执行其他sql操作 解决方案二: http://blog.csdn.net/csh624366188/article/details/7305672/ 解决方案三: 这三个

在java中正确使用PostgreSQL大对象和字节流类型的姿势

有人在java中使用getBlob获取所谓的"大对象"失败,问题是用法不对. groovy:000> rs.getBlob("image") ERROR org.postgresql.util.PSQLException: Bad value for type long : \336\255\276\357\336\255\276\357 at org.postgresql.jdbc2.AbstractJdbc2ResultSet.toLong (Abstra

Java中使用JCOM操作Office对象

通过使用COM技术,我们用微软Office应用程序能够建立很多应用程序扩展,但是Java开发人员却无法享受它带来的便利--除非他们拥有方便的Java访问COM的途径(Java-to-COM桥).使用JCom的时候,你可以在Java中控制几乎所有的COM对象,而且它还带有一些用于Excel的强大的辅助类. 在你每次编写用HTML表格样式或Java表格对象显示数据的应用程序的时候,通常都需要带有"导出到Excel"功能.那么头疼的问题就出现了.怎么样实现这种功能呢?在HTML中显示的可以在

JAVA中的指针,引用及对象的clone

Java语言的一个优点就是取消了指针的概念,但也导致了许多程序员在编程中常常忽略了对象与引用的区别,本文会试图澄清这一概念.并且由于Java不能通过简单的赋值来解决对象复制的问题,在开发过程中,也常常要要应用clone()方法来复制对象.本文会让你了解什么是影子clone与深度clone,认识它们的区别.优点及缺点. 看到这个标题,是不是有点困惑:Java语言明确说明取消了指针,因为指针往往是在带来方便的同时也是导致代码不安全的根源,同时也会使程序的变得非常复杂难以理解,滥用指针写成的代码不亚于

Java中使用JCOM操作Office对象_JSP编程

通过使用COM技术,我们用微软Office应用程序能够建立很多应用程序扩展,但是Java开发人员却无法享受它带来的便利--除非他们拥有方便的Java访问COM的途径(Java-to-COM桥).使用JCom的时候,你可以在Java中控制几乎所有的COM对象,而且它还带有一些用于Excel的强大的辅助类. 在你每次编写用HTML表格样式或Java表格对象显示数据的应用程序的时候,通常都需要带有"导出到Excel"功能.那么头疼的问题就出现了.怎么样实现这种功能呢?在HTML中显示的可以在

java中利用Comparator进行复杂对象Collection的排序

需求场景描述: 需要对一个Collection进行某种方式的排序.比如一个User对象的集合,我们需要按公司和姓名进行排序.User对象如下:  代码如下 复制代码 package com.guoweiwei.test.comparator; public class User { private String name; private String sex; private String company; User(){}; User(String name, String sex, Str