前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >使用“空”对象替代引用是否为空判断

使用“空”对象替代引用是否为空判断

作者头像
用户1608022
发布于 2018-04-11 06:40:49
发布于 2018-04-11 06:40:49
8K00
代码可运行
举报
运行总次数:0
代码可运行

使用Null对象替代引用是否为空判断

编程语言中最常见运行时异常非NullPointerException莫属,只要程序依赖于外部的输入数据,比如说http请求传递的查询字符串参数、关系数据库连接、磁盘文件读取,空引用异常就无法避免。通常,程序需要满足某些条件才能正常的往下执行,假如这些条件依赖外部输入数据,而这些外部输入的数据肯定无法保证百分百不出错,比如说网络连接失败、数据库用户名密码错误等,当程序被这些节外生枝的障碍打断时,空引用异常就极有可能被引发。

比如说,原本我们调用一个方法,这个方法会执行连接数据库操作并返回一个数据库连接对象。然而,由于某种原因导致连接失败,这个方法并没有照常返回数据库连接对象而是返回一个null值,当我们使用对象时假如不进行是否为空检测,程序就会抛出NullPointerException,但是假如进行检测的话代码又会变得极其丑陋,没有程序员喜欢自己的代码中到处都是if(connection == null)这样的条件判断。

而且这种对象是否为空的判断还会传播,在一系列函数调用的过程中,其中某一个调用返回一个null值, 这个函数调用栈中所有的调用都有可能受到波及,直到最外层的调用。这些函数中会出现很多是否为空的判断,严重影响代码的美观程度、可读性,甚至还增加了出BUG的几率。

空引用问题是永远无法避免的, 除非从语言层面进行解决, 现在一些现代的新语言的设计已经引入避免此问题的机制。但是一些年纪较大的语言, 比如说Java,只能通过一些代码编写技巧来尽量弱化空引用带来的问题。「使用Null对象代替是否为空判断」是一种流行的解决此问题的技巧。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Main {
    public static void main(String[] args) {
        getWorstLanguage(false).toString();
        getBestLanguage(false).toString();
    }
    
    public  static String getWorstLanguage( boolean exists) {
        if(exists ) {
            return "Java";
        } else {
            return "";
        }
    }
    
    public static String getBestLanguage( boolean exists ) {
        if( exists ) {
            return "PHP";
        } else {
            return null;
        }
    }
}

main方法中第二行代码执行会抛出空引用异常。 其实两个方法的if条件都没有被满足,然而它们一个返回长度为0的空字符串,一个返回null, 空字符串虽然没有实际意义,但却并非是空引用, 因此在其上执行操作不会抛出空引用异常,代码也是相对安全的。

想要避免getBestLanguage方法使用时有可能会引发的异常,一般都会这么做

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        String  result = getBestLanguage(false);
        if (result != null) {
            result.toString();
        }

显然这并不如getWorstLanguage方法返回空字符串的方式来的优雅。如果你对字符串的长度有依赖,可以以

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (result.length() == 0 ) {}

这种方式进行判断,至少它没有出现异常的危险。

同样,在方法返回值为其它对象类型的时候也可以借鉴并扩展这种思路。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Customer {
        String _name;
 
        public Customer() { }
 
        public Customer(String name) {
            _name = name;
        }
 
        public String GetName() {
            return _name;
        }
    }
 
    public class Site {
        Customer _customer;
 
        public Site() {
        }
 
        public Site(Customer customer) {
            _customer = customer;
        }
 
        public Customer GetCustomer() {
            return _customer;
        }
    }

有Customer 和 Site  两个类,Site类的GetCustomer会返回一个Customer对象,但假如实例化Site对象时使用无参数构造函数,GetCustomer将返回一个空引用。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        Site site = new Site();
        Customer customer = site.GetCustomer();
        String name = customer == null ? "guest" : customer.GetName();
        System.out.println(name);

像这种方式使用那两个类,在调用GetName方法时, 除非进行是否为空校验,否则程序会抛出空引用异常。 假如site对象和它的GetCustomer会被频繁的调用,将是难以忍受的,因为customer == null 这样的条件判断会充斥在项目代码的各处。

我们可以引入一个“空”对象来改善这个问题

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 public class Customer {
        String _name;
 
        public Customer() { }
 
        public Customer(String name) {
            _name = name;
        }
 
        public String GetName() {
            return _name;
        }
 
 
        public boolean IsNull()
        {
            return false;
        }
    }
 
    public class NullCustomer extends Customer {
        public NullCustomer() {}
 
        @Override
        public boolean IsNull() {
            return true;
        }
 
        @Override
        public String GetName() {
            return "guest";
        }
    }
 
    public static class Site {
        Customer _customer;
 
        public Site() {
        }
 
        public Site(Customer customer) {
            _customer = customer;
        }
 
        public Customer GetCustomer() {
            return _customer == null ? new NullCustomer(): _customer;
        }
    }

Customer类添加了一个IsNull的实例方法。

Site 类的GetCustomer方法内部进行了_customer 成员是否为空的判断,这其实就是把原来在外面的空引用判断提取到了类的内部,把逻辑给封装了起来。

与此同时, 我们引入了NullCustomer类型,它继承至Customer,是一个Customer的特例,表示Site对象中_customer成员为空的情况,替代它非空时的行为, 这正如他的命名NullCustomer。

原本调用Site对象GetCustomer有可能返回的null值被NullCustomer类的实例所代替, 这样代码的外部可以放心的使用GetCustomer的返回值,不用再提心吊胆的生怕返回空值,也不用做是否为空的判断。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void main(String[] args) {
        Site site = new Site();
        Customer customer = site.GetCustomer();
        String name = customer.GetName();
        System.out.println(name);
    }

如果要确定GetCustomer的返回值是否为空的情况,可用调用customer对象的IsNull方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        Customer customer = site.GetCustomer();
        if(customer.IsNull()) {
            
        }

因为不管是Customer 类还是NullCustomer都实现了这个方法, 并且Customer的IsNull方法返回的false, NullCustomer类重写了重Customer继承来的IsNull方法,并返回为true,这种利用多态来面向接口编程的方式,正好满足了我们的需求。

总而言之,引用“空”对象可以很好的解决空引用这个牛皮癣似的问题。然而,引入这个机制还需要跟代码的实际情况结合,假如某个对象为空的情况只出现有限的几次,那引入这种机制显得有些杀鸡用牛刀的味道了,使用是否为空判断反而更加轻松;当某个对象是否为空的判断频繁的出现在代码之中, 那么使用“空”对象来代替if判断才有实际的意义。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-02-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 带你撸出一手好代码 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
重构·改善既有代码的设计.04之重构手法(下)完结
本文是代码重构系列的最后一篇啦。前面三篇《重构·改善既有代码的设计.01之入门基础》、《重构·改善既有代码的设计.02之代码的“坏味道”》、《重构·改善既有代码的设计.03之重构手法(上)》介绍了基础入门,代码异味,还有部分重构手法。今天继续总结重构手法下篇,从条件表达式、函数调用、以及类继承关系上阐述了各种重构手法,希望对项目能有所帮助。另外本文更新后该系列就完结了,感谢各位看官的指点。
有一只柴犬
2024/01/25
2230
重构·改善既有代码的设计.04之重构手法(下)完结
Java 中字符串判空相关方法:`isEmpty`、`isBlank`与`isNull`的深度解析
在Java编程中,处理字符串时经常需要判断字符串的状态,尤其是判断其是否为空。Java提供了多种方式来进行这样的判断,其中isEmpty、isBlank和isNull(这里的isNull主要在数据库或特定框架相关场景)是比较常见的概念,但它们的功能和应用场景各有不同。
Yeats_Liao
2025/01/20
7520
Java 中字符串判空相关方法:`isEmpty`、`isBlank`与`isNull`的深度解析
设计模式-空对象模式
一般情况在编写代码的时候判断为空需要通过null==来判断,而这样的写法很难看,一眼看下去几百行代码,密密麻麻都是这些判断,代码很不优雅,有时还漏判还会导致空指导异常。这个问题,java的空对象模式很不错的解决方案,可以做到优雅判断。
逍遥壮士
2020/09/18
9380
设计模式实战-空对象模式,你肯定不知道,但是项目中会常用到到
受 GOF(Gang of Four,四人组)《设计模式》一书的影响,让人误以为设计模式只有 23 种,其实不然,除了《设计模式》介绍的 23 种设计模式外,还有很多经典的设计模式,例如我们本文将要介绍的空对象模式。
架构师修炼
2020/07/20
7890
设计模式实战-空对象模式,你肯定不知道,但是项目中会常用到到
一个面向对象的Java客户管理系统
1 项目目录 image.png 2 CMUtility 工具类 package com.binbin.p2.util; import java.util.*; /** CMUtility工具类: 将不同的功能封装为方法,就是可以直接通过调用方法使用它的功能,而无需考虑具体的功能实现细节。 */ public class CMUtility { private static Scanner scanner = new Scanner(System.in); /** 用于界面菜单的选择。该
Linuxcc
2022/02/07
7280
java项目:客户管理系统
源码已经打包在博客末尾,有需要的话自行下载。 java 项目: 客户信息管理系统 环境: ​ Idea 集成开发工具 技术点: 面向对象 数组 项目结构: 20200801181546.png 20200801180817.png 代码展示: 【bean】 Customer.java public class Customer { private String name; // 姓名 private char gender; // 性别 private int age; // 年龄
OY
2022/03/12
2.6K0
java项目:客户管理系统
JAVA8实战 - Optional工具类
没错,这又是一个新的专栏,JAVA8可以说是JAVA划时代的一个版本,几乎是让JAVA焕发了第三春(第二春在JDK5),当然里面的新特性也是十分重要的,虽然Java现在都已经到了10几的版本,但是国内多数使用的版本还是JAVA8,所以这个系列将会围绕Java8的新特性和相关工具做一些总结。希望对大家日常学习和工作中有所帮助。
阿东
2021/08/16
1.8K0
工厂模式和策略模式结合使用的案例介绍
在前面的文章中,我们有单独介绍过工厂模式和策略模式,这两种模式是实际开发中经常会用到的,今天来介绍下将两种模式结合起来使用的场景及案例,这种结合的模式也更加的常用,能帮助我们减少if-else的使用的同时,让代码逻辑也清晰简洁、扩展性高。
用户4283147
2022/10/08
1.2K0
为什么不建议你用a.equals(b)判断对象相等
1.a.equals(b), a 是null, 抛出NullPointException异常。
JAVA葵花宝典
2021/06/17
4040
二十六、空对象模式 ( Null Object Pattern )
在空对象模式(Null Object Pattern)中,一个空对象取代 NULL 对象实例的检查
botkenni
2022/09/23
3690
二十六、空对象模式 ( Null Object Pattern )
还在用 if(obj!=null) 做非空判断?带你快速上手 Optional 实战性理解!
相信不少小伙伴已经被java的NPE(Null Pointer Exception)所谓的空指针异常搞的头昏脑涨,有大佬说过“防止 NPE,是程序员的基本修养。”但是修养归修养,也是我们程序员最头疼的问题之一,那么我们今天就要尽可能的利用Java8的新特性 Optional来尽量简化代码同时高效处理NPE(Null Pointer Exception 空指针异常)
JAVA葵花宝典
2020/06/04
8.4K0
MySQL数据库查询对象空值判断与Java代码示例
在现代软件开发中,数据库是一个不可或缺的组成部分。而MySQL作为一种常见的关系型数据库管理系统,广泛应用于各种应用程序中。在开发过程中,我们经常需要从MySQL数据库中检索数据,并在代码中对查询结果进行处理。然而,查询结果并不总是如我们所期望,有时可能为空。因此,在处理从MySQL数据库查询的对象时,我们需要谨慎地考虑如何处理可能的空值情况,以确保应用程序的稳定性和可靠性。
疯狂的KK
2023/09/18
1.1K0
MySQL数据库查询对象空值判断与Java代码示例
还只会 null != obj 判空,10招让你彻底告别空指针异常!
NPE异常相信 Java 程序员都很熟悉,是 NullPointerException 的缩写;最近业务需求开发的有点着急,测试环境就时不时的来个NPE异常,特别的头疼;作为出镜率最高的异常之一,一旦入行 Java 开发,可以说它将伴随着你整个职业生涯;不管是新手小白、还是老司机,对NPE异常那是又“爱”又狠,爱的主要原因是处理起来简单,恨当然是一个不小心就会踩坑;为了提高代码的质量,NPE异常是必须要消灭掉的;
一行Java
2023/09/04
1K0
还只会 null != obj 判空,10招让你彻底告别空指针异常!
java常用数据判空、比较和类型转换
java 开发中我们经常会用到的数据判空、数据比较和不同数据之间的类型转换,尤其数据判空可以让我们避免经常会出现的 NullPointerException 空指针异常报错。
人人都是码农
2024/06/30
1990
优秀!高级Java都这样优雅处理空值
在笔者几年的开发经验中,经常看到项目中存在到处空值判断的情况,这些判断,会让人觉得摸不这头绪,它的出现很有可能和当前的业务逻辑并没有关系。但它会让你很头疼。
JAVA葵花宝典
2020/03/02
1.8K0
java常用数据判空、比较和类型转换
java 开发中我们经常会用到的数据判空、数据比较和不同数据之间的类型转换,尤其数据判空可以让我们避免经常会出现的 NullPointerException 空指针异常报错。
闻说社
2024/12/06
1270
java常用数据判空、比较和类型转换
Optional进行优雅非空判断
那么进入今天的正题吧~今天带来的是1.8的这个类Optional,Optional在英文中是可选的意思,他在java中可以作为非空判断,是妥妥的炫技哦!
阿超
2022/08/16
2.7K0
java 判断对象是否为空「建议收藏」
大家好,又见面了,我是你们的朋友全栈君。 java 中如何判断对象是否为空呢,特别是一个未知的对象? 下面是一个通用的方法,判断字符串是否为空,集合是否为空,数组是否为空: /** * 判断对象或
全栈程序员站长
2022/07/01
9630
客户信息管理系统_销售找客户最好的app
客户信息管理系统,功能如下: (1)添加客户信息 (2)修改客户信息 (3)删除客户数据 (4)查询客户列表 (5)所有数据通过JDBC保存到MySql数据库中 1,数据库名:cms_hisoft 2,表名:users 3,字段列表和类型: id,int,主键,自动增长 name,varchar(20),姓名 gender,varchar(5),性别 age,int,年龄 phone…
全栈程序员站长
2022/11/02
1.5K0
Java判断对象是否为空的方法:isEmpty,null,” “
今天修改辞职同事遗留的代码才发现这个问题,不能用isEmpty来判断一个对象是否为null,之前没在意这个问题,在报了空指针之后才发现这个问题。
全栈程序员站长
2022/07/01
6.4K0
Java判断对象是否为空的方法:isEmpty,null,” “
推荐阅读
相关推荐
重构·改善既有代码的设计.04之重构手法(下)完结
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验