当前位置: 首页 > news >正文

项目中别用 “! = null“ 做判空了

问题

为了避免空指针调用,我们经常会看到这样的语句:

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

最终,项目中会存在大量判空代码,丑陋繁杂。。。如何避免这种情况?是否滥用了判空?
最终,项目中会存在大量判空代码,丑陋繁杂。。。如何避免这种情况?是否滥用了判空?

精华回答

这是初、中级程序猿经常会遇到的问题。他们总喜欢在方法中返回null,因此,在调用这些方法时,也不得不去判空。另外,也许受此习惯影响,他们总潜意识地认为,所有的返回都是不可信任的,为了保护自己程序,就加了大量的判空。

吐槽完毕,回到这个题目本身:

进行判空前,请区分以下两种情况:

1、null 是一个有效有意义的返回值(Where null is a valid response in terms of the contract; and)

2、null是无效有误的(Where it isn’t a valid response.)

你可能还不明白这两句话的意思,不急,继续往下看,接下来将详细讨论这两种情况。

先说第2种情况

null就是一个不合理的参数,就应该明确地中断程序,往外抛错误。这种情况常见于api方法。例如你开发了一个接口,id是一个必选的参数,如果调用方没传这个参数给你,当然不行。你要感知到这个情况,告诉调用方“嘿,哥们,你传个null给我做甚"。

相对于判空语句,更好的检查方式有两个

(1)assert语句,你可以把错误原因放到assert的参数中,这样不仅能保护你的程序不往下走,而且还能把错误原因返回给调用方,岂不是一举两得。(原文介绍了assert的使用,这里省略)

(2)也可以直接抛出空指针异常。上面说了,此时null是个不合理的参数,有问题就是有问题,就应该大大方方往外抛。

第1种情况会更复杂一些。

这种情况下,null是个”看上去“合理的值,例如,我查询数据库,某个查询条件下,就是没有对应值,此时null算是表达了“空”的概念。

这里给一些实践建议:

1、假如方法的返回类型是collections,当返回结果是空时,你可以返回一个空的collections(empty list),而不要返回null,这样调用侧就能大胆地处理这个返回,例如调用侧拿到返回后,可以直接print list.size(),又无需担心空指针问题。(什么?想调用这个方法时,不记得之前实现该方法有没按照这个原则?所以说,代码习惯很重要!如果你养成习惯,都是这样写代码(返回空collections而不返回null),你调用自己写的方法时,就能大胆地忽略判空。
2、返回类型不是collections,又怎么办呢?

那就返回一个空对象(而非null对象),下面举个“栗子”,假设有如下代码:

public interface Action {void doSomething();}public interface Parser {Action findAction(String userInput);}

其中,Parse有一个接口FindAction,这个接口会依据用户的输入,找到并执行对应的动作。假如用户输入不对,可能就找不到对应的动作(Action),因此findAction就会返回null,接下来action调用doSomething方法时,就会出现空指针。

解决这个问题的一个方式,就是使用Null Object pattern(空对象模式)

改造后

类定义如下,这样定义findAction方法后,确保无论用户输入什么,都不会返回null对象。

public class MyParser implements Parser {private static Action DO_NOTHING = new Action() {public void doSomething() { /* do nothing */ }};public Action findAction(String userInput) {// ...if ( /* we can't find any actions */ ) {return DO_NOTHING;}}}

对比下面两份调用实例

1、冗余:每获取一个对象,就判一次空

Parser parser = ParserFactory.getParser();
if (parser == null) {// now what?// this would be an example of where null isn't (or shouldn't be) a valid response
}
Action action = parser.findAction(someInput);
if (action == null) {// do nothing} else {action.doSomething();}

精简

ParserFactory.getParser().findAction(someInput).doSomething();

因为无论什么情况,都不会返回空对象,因此通过findAction拿到action后,可以放心地调用action的方法。

其他回答精选:

1、如果要用equal方法,请用object<不可能为空>.equal(object<可能为空>))

例如使用:

"bar".equals(foo)

而不是

foo.equals("bar")

2、Java8或者guava lib中,提供了Optional类,这是一个元素容器,通过它来封装对象,可以减少判空。不过代码量还是不少。不爽。

3、如果你想返回null,请停下来想一想,这个地方是否更应该抛出一个异常。

相关文章:

项目中别用 “! = null“ 做判空了

问题 为了避免空指针调用&#xff0c;我们经常会看到这样的语句: if (someobject ! null) {someobject.doCalc();}最终&#xff0c;项目中会存在大量判空代码&#xff0c;丑陋繁杂。。。如何避免这种情况&#xff1f;是否滥用了判空&#xff1f; 最终&#xff0c;项目中会存在…...

MySQL数据库——MySQL子查询

子查询是 MySQL 中比较常用的查询方法&#xff0c;通过子查询可以实现多表查询。子查询指将一个查询语句嵌套在另一个查询语句中。子查询可以在 SELECT、UPDATE 和 DELETE 语句中使用&#xff0c;而且可以进行多层嵌套。在实际开发时&#xff0c;子查询经常出现在 WHERE 子句中…...

工具链和其他-超级好用的web调试工具whistle

目录 whistle介绍 整体结构 能力 规则 6个使用场景示例 1.修改Host 2.代理 3.替换文件&#xff08;线上报错时&#xff09; 4.替换UA 5.远程调试 6.JS注入 互动 whistle介绍 整体结构 安装&#xff1a; npm install whistle -g cli&#xff1a;whistle help 启动…...

ROS第四十三节——定位

https://download.csdn.net/download/qq_45685327/87725276 1.新建launch文件 关于launch文件的实现&#xff0c;在amcl功能包下的example目录已经给出了示例&#xff0c;可以作为参考&#xff0c;具体实现: roscd amcl ls examples gedit amcl_diff.launch 该目录下会列出两…...

2023年第二十届五一数学建模竞赛题目 C题详细思路

详细思路以及发布视频版&#xff0c;大家可以去观看&#xff0c;这里是对应的文字版&#xff0c;内容相差不多。 C题&#xff1a;“双碳”目标下低碳建筑研究 C题的问题设置其实是本次比赛最简单的一道&#xff0c;就是简单的综合评价预测模型。真正提升C题难度的其实是C题的…...

模块化编程原理示意图--CommonJS 模块编程--ES6 模块编程思路分析/图解--三种导出形式--全部代码示例

目录 模块化编程 基本介绍 模块化编程原理示意图 模块化编程分类 CommonJS 模块编程 介绍 应用实例 1. 需求说明 2. 思路分析/图解 3. 代码实现 function.js use.html use.js ES6 模块编程 介绍 需求说明 思路分析/图解 代码实现 common.js use_common.js …...

Ansys Zemax | 如何模拟双折射偏振器件

这篇文章介绍了什么是双折射现象、如何在OpticStudio中模拟双折射 (birefringence)、如何模拟双晶体的双折射偏振器以及如何计算偏振器的消光比。&#xff08;联系我们获取文章附件&#xff09; 什么是双折射现象 一般的光学材料都是均匀的各向同性的&#xff0c;也就是说无论光…...

Java关键字之:this

一、this关键字的使用 1、this可以用来修饰、调用&#xff1a;属性、方法、构造器 2、this修饰属性和方法 this理解为&#xff1a;当前对象 或 当前正在创建的对象 在类的方法中。我们可以使用“this.属性"或”this.方法“的方式。调用当前对象属性或者方法。但是&#…...

嵌入式Linux驱动开发(九)Linux中断

1. Linux中断简介 1&#xff09;中断号 linux内核中使用一个int变量表示中断号。 2&#xff09;申请中断&#xff1a; 该函数可以自动激活中断&#xff0c;但是可能引起睡眠&#xff0c;所以需要小心使用。 int request_irq(unsigned int irq, //要申请中断的中断号irq_ha…...

数据库系统-并发控制

文章目录 一、为什么要并发控制1.2 并发控制解决的问题1.2.1 脏读1.2.2 幻读1.2.3 不可重复读1.2.4 数据丢失问题 二、事务调度及可串行性2.1 事务2.1.1 事务的宏观2.1.2 事务的微观2.1.3 事务的特性 ACID 2.2 事务调度与可串行性2.3 冲突可串行化判定 三、基于封锁的并发控制方…...

Java8 教程_编程入门自学教程_菜鸟教程-免费教程分享

教程简介 Java 8 (又称为 jdk 1.8) 是 Java 语言开发的一个主要版本。 Java 8 是oracle公司于2014年3月发布&#xff0c;可以看成是自Java 5 以来最具革命性的版本。Java 8为Java语言、编译器、类库、开发工具与JVM带来了大量新特性。 Java 8入门教程 - 从简单的步骤了解Java…...

从零开始学架构——高可用存储架构

双机架构 存储高可用方案的本质都是通过将数据复制到多个存储设备&#xff0c;通过数据冗余的方式来实现高可用&#xff0c;其复杂性主要体现在如何应对复制延迟和中断导致的数据不一致问题。因此&#xff0c;对任何一个高可用存储方案&#xff0c;我们需要从以下几个方面去进…...

连ChatGPT都不懂的五一调休,到底怎么来的?

今天是周几&#xff1f; 你上了几天班了&#xff1f; 还要上几天班放假&#xff1f; 五一啥安排&#xff1f; 出行的票抢到了吗&#xff1f; 调休到底是谁发明的&#xff1f;&#xff01; 五一劳动节是要劳动吗&#xff1f; 为什么昨天是周一&#xff0c;今天还是周一&a…...

AES工作流程

工作流程 模式 1&#xff1a;加密 ⚫ 复位EN 重置AES模块 ⚫ 设置模式寄存器mode[1:0]00&#xff0c;设置流数据处理模式寄存器CHMOD[1:0] ⚫ 写AES_KEYRx寄存器&#xff0c;CTR和CBC模式下写AES_IVRx寄存器 ⚫ 写EN1&#xff0c;使能AES ⚫ 写AES_DINR 寄存器4次 ⚫ 等待CCF标…...

C++11

C11 统一的列表初始化 在介绍这里的列表初始化之前&#xff0c;首先我认为这是一个比较鸡肋的功能特性&#xff0c;而且使用起来会和之前C98时有些区别。 // 首先可以定义普通的内置类型的变量int x1 1;int x2 { 1 };int x3{ 1 }; // 这样看起来着实有些怪int arry1[] { 1,…...

ubuntu18.04 配置zlmediakit 支持ffmpeg转码记录

1、zlmediakt 默认不支持ffmepg转码&#xff0c;需要在根目录下的CamkeLists.txt里面option(ENABLE_FFMPEG "Enable FFmpeg" OFF) 将OFF改成ON, 删除原有的build目录&#xff0c;sudo mkdir build. cd build,cmake .. 这样在编译生成文件夹release/linux/debug/生…...

H68K配置路由功能

系统环境Armbian ubuntu系统 参考 如何使用Debian/Ubuntu等Linux做软路由&#xff08;物理机版本&#xff0c;非虚拟机容器版&#xff09; - 知乎 https://zhuanlan.zhihu.com/p/587068225 按照他操作的结果,就是只有一个网卡正常 最后一顿操作就出现了我这么个配置 更新源…...

*2.5 迭代法的收敛阶与加速收敛方法

学习目标&#xff1a; 了解迭代法的基本概念和原理。学习者需要理解迭代法的基本概念和原理&#xff0c;包括迭代过程、迭代格式、收敛性等基本概念。 熟练掌握迭代法的收敛阶和收敛速度。学习者需要了解迭代法的收敛阶和收敛速度&#xff0c;掌握如何计算迭代法的收敛阶和收敛…...

仪表板展示 | X-lab开放实验室GitHub开源项目洞察大屏

背景介绍 X-lab开放实验室是一个开源软件产业开放式创新的共同体&#xff0c;由来自国内外著名高校、创业公司、部分互联网与IT企业的专家学者与工程师所构成&#xff0c;目前已在包括开源治理标准制定、开源社区行为度量与分析、开源社区流程自动化、开源全域数据治理与洞察等…...

【c语言】五大内存区域 | 堆区详解

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 给大家跳段街舞感谢支持&#xff01;ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用

1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解

JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用&#xff0c;结合SQLite数据库实现联系人管理功能&#xff0c;并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能&#xff0c;同时可以最小化到系统…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...