空对象(null Object) in Java

本文介绍了一种避免在代码中频繁检查null值的方法——空对象模式。通过定义空对象并使用多态特性,可以在不改变原有接口的情况下优雅地处理空值问题。

相信大家一定在开发中见过并且写过类似这样的代码:

public Book getBook(int id) {  
    if (id < 0) {  
        return null;  
    }  
    return new Book(1, "Design Pattern", 100);  
}  

Book book = getBook(-1);  
if (book != null) {                   
}

系统在使用对象的相关功能时,总要检查对象是否为null,如果不为null,我们才会调用它的相关方法,完成某种逻辑。这样的检查在一个系统中出现很多次,相信任何一个设计者都不愿意看到这样的情况。为了解决这种问题,我们可以可以引入空对象,这样,我们就可以摆脱大量程式化的代码,对代码的可读性也是一个飞跃。

等等,空对象是什么?它和null什么关系?
空对象是一个没有实质性内容的对象,但他并不为null。你可以把空对象理解为一个空箱子,这个物品还是存在的,只不过仅仅是一个壳,没有实质性的东西。
我们需要对原有的代码进行重构,把所有返回null的地方都替换成返回一个与之对应的空对象,然后再客户端调用时不再使用book==null这种方式判断是否为空,而是替换成book.isNull()的方式。下面我们就一步一步来实现这种模式。

首先,我们需要定义一个Nullable接口:

public interface Nullable {  
    /** 
     * 对象是否为空 
     * @return 
     */  
    public boolean isNull();  
}  

这个接口定义了一个isNull()的方法,来表示一个对象是否为空。
然后我们让Book实现此接口:

public class Book implements Nullable {  

    private int id;  
    private String name;  
    private double price;  

    public Book() {  
    }  

    public Book(int id, String name, double price) {  
        this.id = id;  
        this.name = name;  
        this.price = price;  
    }  

    @Override  
    public boolean isNull() {  
        return false;  
    }  

    /** 
     * 创建一个NullBook实例代表空对象 
     * @return 
     */  
    public static Book createNullBook() {  
        return new NullBook();  
    }  

    /** 
     * setters & getters 
     */  
}

在Book中实现了isNull()方法,并返回false;另外Book还定义了一个静态的createNullBook方法,返回了一个NullBook的实例,NullBook是什么呢,我们来看一下:

public class NullBook extends Book {  
    @Override  
    public boolean isNull() {  
        return true;  
    }  
}  

NullBook继承了Book,并在isNull()方法中返回true,这个NullBook其实就是我们上面提到的空对象,仅仅是个空箱子而已。
然后我们定义一个BookService类,用以模拟获取Book的接口方法:

public class BookService {  
    public Book getBook(int id) {  
        if (id < 0) {  
            //返回一个空对象  
            return Book.createNullBook();             
        }  
        return new Book(id, "Design Pattern", 100);  
    }  
}  

在getBook(int id)中,如果id<0时,则返回一个NullBook的实例,在客户端调用isNull()方法时则返回true,表示是空对象;如果id>=0时,则返回一个Book的实例,在客户端调用isNull()方法时则返回false,表示对象不为空,可以调用相关方法取得数据。对于我们的客户端来讲,返回的都是一个Book类型的对象,我们并不清楚返回的到底是真正的Book实例还是空对象NullBook实例,但是我们并不担心,因为有一点可以肯定的是,我们都可以放心的调用isNull()方法,因为它会根据运行期对象的类型返回一个正确的值。

多态的最根本好处在于:你不必再向对象询问“你是什么类型”而后根据得到的答案调用对象的某个行为,你只管调用该行为就是了,其他的一切事情多态机制会为你妥善处理。

最后再来看一下客户端是如何实现对象为空的判断的:

public class Client {  
    public static void main(String[] args) {  
        BookService service = new BookService();  
        Book book = service.getBook(-1);  
        if (book.isNull()) {  
            System.out.println("not found!");  
        } else {  
            System.out.println("name:" + book.getName());  
            System.out.println("price:" + book.getPrice());  
        }  
    }  
}  

原文:http://blog.youkuaiyun.com/liuhe688/article/details/6586458

 2012年11月02日 20:11:00 | 分类: 设计模式 | 标签: object

<think> 首先,用户的问题是:“我想查找在Java中判断对象是否为空的方法”,意思是“I want to find methods to determine if an object is null in Java”。 我有几个引用: - 引用[1]:描述了Java中判断对象是否为空的不同方法,包括使用条件判断、Optional类、Apache Commons Lang库等。 - 引用[2]:类似,讨论了使用==、Objects.isNull()instanceof、Optional类。 - 引用[3]:提到了StringUtils.isEmpty用于字符串。 - 引用[4]:针对List判断为空的方法,推荐使用isEmpty()。 - 引用[5]:涉及StringUtils.isEmpty。 用户的问题是关于判断对象是否为空,所以我需要覆盖Java中处理null对象的一般方法。 系统指令: - 所有行内数学表达式必须用$...$,但这里不涉及数学,所以可能不需要。 - 独立公式用$$...$$,但同样不相关。 - LaTeX语法正确:确保任何数学部分正确,但这里没有数学。 - 使用中文回答:所有响应必须用中文。 - 生成相关问题:在回答末尾,添加相关问题部分。 - 引用中引用的段落末尾添加引用标识,例如[^1]。 - 用户可见层:回答结构清晰,逐步解决问题,确保真实可靠。 回答结构: - 以清晰的方式解释方法。 - 因为这是技术问题,提供代码示例会更好。 - 参考引用来支持信息。 - 在末尾添加相关问题。 关键方法从引用中提取: 1. 使用==或!=:直接比较对象和null。 2. 使用Objects.isNull()Java 7引入,安全处理null。 3. 使用Optional类:Java 8引入,优雅处理。 4. 使用Apache Commons Lang库的StringUtils或类似工具。 5. 对于集合如List,使用isEmpty()或size()==0。 确保覆盖一般对象和特定类型如字符串或集合。 步骤: 1. 介绍问题:空指针异常的常见错误,判断空对象的重要性。 2. 逐步列出方法: - 基本方法:使用== null - 使用Objects.isNull() - 使用Optional - 使用库如Apache Commons - 针对字符串和集合的特定方法 3. 提供代码示例。 4. 添加引用标识。 5. 结束部分添加相关问题。 相关问题生成: - 基于主题,生成3-4个相关问题。 - 例如:如何避免空指针异常?Java 8 Optional的更多用法?Apache Commons库的使用?等。 最终输出: - 用中文。 - 结构:解释、方法列表、代码示例、相关问题。 </think> ### Java中判断对象是否为空的方法详解 在Java编程中,判断对象是否为空是防止空指针异常(NullPointerException)的关键步骤。空指针异常是常见的程序错误,会导致应用崩溃或不可预测行为。正确判断对象空值能提高代码健壮性和可维护性。以下是Java中判断对象是否为空的主要方法,我将逐步解释每种方法的原理、优缺点和代码示例。 #### 1. **基本方法:使用`== null`或`!= null`** - **原理**:直接比较对象引用与`null`值。这是最基础且高效的方式,适用于所有对象类型。 - **优点**:简单直接,无需额外依赖。 - **缺点**:如果对象为`null`时调用其方法,仍可能引发空指针异常。 - **代码示例**: ```java Object obj = null; if (obj == null) { System.out.println("对象为空"); // 输出:对象为空 } else { System.out.println("对象不为空"); } ``` 这种方法在判断字符串或自定义对象时通用[^2]。 #### 2. **使用`Objects.isNull()`方法(Java 7及以上)** - **原理**:`java.util.Objects`类提供的静态方法,安全地检查对象是否为`null`。它内部使用`obj == null`实现,但能避免某些边界问题。 - **优点**:代码更易读,且能处理`null`参数而不抛异常。 - **缺点**:需要Java 7或更高版本。 - **代码示例**: ```java import java.util.Objects; Object obj = null; if (Objects.isNull(obj)) { System.out.println("对象为空"); // 输出:对象为空 } else { System.out.println("对象不为空"); } ``` 这个方法特别适合在lambda表达式或流处理中使用[^2]。 #### 3. **使用`Optional`类(Java 8及以上)** - **原理**:`java.util.Optional`类封装对象,提供优雅的空值处理。`Optional.ofNullable()`创建Optional实例,`isPresent()`检查对象是否存在。 - **优点**:支持链式调用,减少嵌套if语句,提升代码可读性。 - **缺点**:引入额外对象开销,适用于复杂场景。 - **代码示例**: ```java import java.util.Optional; Object obj = null; Optional<Object> optional = Optional.ofNullable(obj); if (optional.isPresent()) { System.out.println("对象不为空"); } else { System.out.println("对象为空"); // 输出:对象为空 } ``` 结合`orElse()`或`orElseGet()`方法,可以设置默认值[^2]。 #### 4. **使用第三方库(如Apache Commons Lang)** - **原理**:库如Apache Commons Lang提供工具类(如`StringUtils.isEmpty()`)简化空值检查。 - **针对字符串**:`StringUtils.isEmpty(CharSequence cs)`检查字符串为`null`或空串。 - **针对其他对象**:自定义工具方法扩展。 - **优点**:减少样板代码,支持多类型检查。 - **缺点**:需引入外部依赖。 - **代码示例**: ```java import org.apache.commons.lang3.StringUtils; String str = null; if (StringUtils.isEmpty(str)) { System.out.println("字符串为空"); // 输出:字符串为空 } else { System.out.println("字符串不为空"); } ``` 对于非字符串对象,可扩展类似工具类[^3][^5]。 #### 5. **针对特定类型的方法** - **集合类型(如List)**:优先使用`isEmpty()`而非`size() == 0`,因为`isEmpty()`语义更清晰。 ```java import java.util.List; import java.util.ArrayList; List<String> list = new ArrayList<>(); if (list.isEmpty()) { // 推荐使用 System.out.println("List为空"); } ``` `size() == 0`在集合为空时也有效,但`isEmpty()`更易读[^4]。 - **数组**:需单独检查长度,例如`if (array == null || array.length == 0)`。 #### 最佳实践建议 - **优先选择**:对于简单场景,使用`Objects.isNull()`或`== null`;对于复杂逻辑,使用`Optional`。 - **避免错误**:不要依赖`instanceof`作为空值检查工具,因为它只在对象非`null`时有效。 - **性能注意**:基本方法`== null`性能最优,`Optional`或库方法稍慢但可读性高。 - **综合示例**: ```java public class NullCheckDemo { public static void main(String[] args) { Object obj = null; // 使用Objects.isNull() if (Objects.isNull(obj)) { System.out.println("Objects.isNull()检测为空"); } // 使用Optional Optional.ofNullable(obj).ifPresentOrElse( o -> System.out.println("Optional检测不为空"), () -> System.out.println("Optional检测为空") ); } } ``` 通过以上方法,您可以有效避免空指针异常。记住,选择方法时应考虑代码上下文和Java版本兼容性[^1][^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值