系统错误null是什么意思_为什么NULL是错误的?

系统错误null是什么意思

Java中NULL用法的简单示例:

public Employee getByName(String name) {int id = database.find(name);if (id == 0) {return null;}return new Employee(id);
}

这种方法有什么问题?

它可能返回NULL而不是对象-这是错误的。 在面向对象的范例中, NULL是一种可怕的做法,应不惜一切代价避免使用NULL 。 已经有一些关于这个意见已经发布,包括空引用,数十亿美元的错误由Tony Hoare的介绍和整个对象思想由大卫-韦斯特的书。

在这里,我将尝试总结所有的参数,并举例说明如何避免使用NULL并使用适当的面向对象的结构代替它们。

基本上,可以使用NULL两种替代方法。

第一个是Null Object设计模式(最好的方法是使其成为常数):

public Employee getByName(String name) {int id = database.find(name);if (id == 0) {return Employee.NOBODY;}return Employee(id);
}

第二种可能的替代方法是在无法返回对象时抛出异常 ,从而快速失败 :

public Employee getByName(String name) {int id = database.find(name);if (id == 0) {throw new EmployeeNotFoundException(name);}return Employee(id);
}

现在,让我们看看反对NULL的参数。

除了上面提到的Tony Hoare的演示文稿和David West的书以外,我在写这篇文章之前阅读了这些出版物:Robert Martin的Clean Code ,Steve McConnell的Code Complete ,John Sonmez的“ No”到“ Null” , 是否返回无效的不良设计? StackOverflow上的讨论。

临时错误处理

每次获取对象作为输入时,都必须检查它是否为NULL或有效的对象引用。 如果忘记检查,则NullPointerException (NPE)可能会在运行时中断执行。 因此,您的逻辑将受到多次检查以及if / then / else分支的污染:

// this is a terrible design, don't reuse
Employee employee = dept.getByName("Jeffrey");
if (employee == null) {System.out.println("can't find an employee");System.exit(-1);
} else {employee.transferTo(dept2);
}

这就是应该用C和其他命令式程序语言处理异常情况的方式。 OOP引入了异常处理,主要是为了摆脱这些临时的错误处理块。 在OOP中,我们让异常冒泡直到它们到达应用程序范围的错误处理程序,并且我们的代码变得更加简洁明了:

dept.getByName("Jeffrey").transferTo(dept2);

考虑NULL引用是过程编程的继承,请改用1)Null对象或2)异常。

模棱两可的语义

为了明确传达其含义,必须将函数getByName()命名为getByNameOrNullIfNotFound() 。 每个返回对象或NULL函数都应该发生相同的情况。 否则,代码阅读器不可避免地会产生歧义。 因此,为了保持语义的明确性,应为函数指定更长的名称。

要摆脱这种歧义,请始终返回真实对象,空对象或引发异常。

有人可能会争辩说,为了性能起见,我们有时必须返回NULL 。 例如,当地图中没有这样的项目时,Java中接口Map get()方法将返回NULL

Employee employee = employees.get("Jeffrey");
if (employee == null) {throw new EmployeeNotFoundException();
}
return employee;

由于Map使用NULL ,因此此代码仅搜索地图一次。 如果我们将Map重构,以便其方法get()在未找到任何内容的情况下将引发异常,则我们的代码将如下所示:

if (!employees.containsKey("Jeffrey")) { // first searchthrow new EmployeeNotFoundException();
}
return employees.get("Jeffrey"); // second search

显然,这种方法的速度是第一种方法的两倍。 该怎么办?

Map界面(对其作者没有冒犯)具有设计缺陷。 它的方法get()应该一直返回一个Iterator以便我们的代码如下所示:

Iterator found = Map.search("Jeffrey");
if (!found.hasNext()) {throw new EmployeeNotFoundException();
}
return found.next();

顺便说一句,这正是C ++ STL map :: find()方法的设计方式。

计算机思维与对象思维

有人知道Java中的对象是指向数据结构的指针,而NULL是指向0x00000000的指针(在Intel x86处理器中为0x00000000 if (employee == null)可以理解if (employee == null)语句。

但是,如果您开始将其作为一个对象来考虑,那么这种说法就没有意义了。 这是从对象角度看我们的代码的样子:

- Hello, is it a software department?
- Yes.
- Let me talk to your employee "Jeffrey" please.
- Hold the line please...
- Hello.
- Are you NULL?

对话中的最后一个问题听起来很奇怪,不是吗?

相反,如果他们在我们请求与Jeffrey通话后挂断电话,则会给我们造成麻烦(异常)。 那时,我们尝试再次致电或通知主管,我们无法联系Jeffrey并完成更大的交易。

或者,他们可以让我们与不是Jeffrey的其他人交谈,但是可以帮助我们解决大多数问题,或者在我们需要“特定于Jeffrey”的东西时拒绝帮助(空对象)。

缓慢失败

上面的代码不是快速失败 ,而是尝试缓慢消失,并杀死其他人。 它没有让所有人都知道出了什么问题并且应该立即开始异常处理,而是向客户端隐藏了此故障。

该参数与上面讨论的“临时错误处理”非常接近。

最好使代码尽可能脆弱,让代码在必要时中断。

使您的方法对它们操作的数据极为苛刻。 如果提供的数据不足或根本不适合该方法的主要使用场景,请让他们通过引发异常来抱怨。

否则,返回一个Null对象,该对象暴露出一些常见行为,并在所有其他调用上引发异常:

public Employee getByName(String name) {int id = database.find(name);Employee employee;if (id == 0) {employee = new Employee() {@Overridepublic String name() {return "anonymous";}@Overridepublic void transferTo(Department dept) {throw new AnonymousEmployeeException("I can't be transferred, I'm anonymous");}};} else {employee = Employee(id);}return employee;
}

可变和不完整的对象

通常, 强烈建议设计时牢记不变性的对象。 这意味着对象在实例化过程中会获得所有必需的知识,并且在整个生命周期中都不会改变其状态。

通常,在延迟加载中使用NULL值,以使对象不完整且可变。 例如:

public class Department {private Employee found = null;public synchronized Employee manager() {if (this.found == null) {this.found = new Employee("Jeffrey");}return this.found;}
}

该技术尽管被广泛使用,但在OOP中却是一种反模式。 主要是因为它使对象负责计算平台的性能问题,而这是Employee对象不应该意识到的。

对象不必管理状态并公开其与业务相关的行为,而必须处理其自身结果的缓存-这就是延迟加载的意义所在。

缓存不是员工在办公室里做的事情,对吗?

解决方案? 请勿以上述原始方式使用延迟加载。 相反,请将此缓存问题移至应用程序的另一层。

例如,在Java中,您可以使用面向方面的编程方面。 例如, jcabi-aspects具有@Cacheable批注,用于缓存方法返回的值:

import com.jcabi.aspects.Cacheable;
public class Department {@Cacheable(forever = true)public Employee manager() {return new Employee("Jacky Brown");}
}

我希望这种分析令人信服,您将停止NULL您的代码!

相关文章

您可能还会发现以下有趣的帖子:

  • Java代码中的典型错误
  • 实用程序类的OOP替代
  • 避免字符串串联
  • 对象应该是不可变的

翻译自: https://www.javacodegeeks.com/2014/09/why-null-is-bad.html

系统错误null是什么意思

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/339809.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql数据库版本不同_mysql数据库版本不同所引起的问题

1.sql_mode不同所引起的问题mysql5.7 ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column lhh.lhh.id which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode…

线性搜索或顺序搜索算法在Java中如何工作? 示例教程

大家好,我之前谈到了二进制搜索算法的工作原理,并分享了在Java中实现二进制搜索的代码。 在那篇文章中,有人问我是否还存在其他搜索算法? 如果数组中的元素未排序,又如何使用二进制搜索算法,该如何搜索呢&a…

junit规则_JUnit规则

junit规则介绍 在本文中,我想展示一个示例,说明如何使用JUnit Rule简化测试。 最近,我继承了一个相当复杂的系统,并未对所有内容进行测试。 甚至经过测试的代码也很复杂。 通常,我看到缺乏测试隔离。 (我将…

mysql server 5.0安装教程_MySQL Server 5.0安装教程

运行MySQL Server 5.0安装程序“setup.exe”,出现如下界面:安装向导启动,按“Next”继续:选择安装类型,为了方便熟悉安装过程,我们选择“Custom”。按“Next”继续:在“Developer Components”上…

Kubernetes集群上的Apache Ignite和Spring第2部分:Kubernetes部署

以前,我们已经成功创建了第一个由Apache Ignite支持的Spring boot Application。 在此博客上,我们将重点介绍Kubernetes方面需要做的事情,以便能够启动我们的应用程序。 如先前博客所述,我们需要制定我们的Kubernetes RBAC策略。…

centos6.5 安装多个mysql_在centos6,5(64位)系统安装多实例mysql5.6

首先你安装个单实例的mysql试一试一 检查你电脑之前是否装了mysqlrpm -qa | grep mysql这条命令只是查看你系统是否使用过yum或者rpm包安装mysql,对用源码包安装的mysql是查不到的,所以基本用不到二 安装编译所需的包yum -y install make gcc-c cmake bi…

hibernate jpa_JPAHibernate替代方案。 如果JPA或Hibernate对于我的项目而言不够好,该怎么办?...

hibernate jpa你好!你好吗? 今天我们将讨论不建议使用JPA / Hibernate的情况。 在JPA领域之外,我们还有哪些选择? 我们将谈论的是: JPA /Hibernate问题 解决一些JPA /Hibernate问题的方法 选择此处描述的框架的标准…

mysql中常见查询表_MySQL中常见查询

1 --1、查询“001”课程比“002”课程成绩高的所有学生的学号;2 SELECT a.s FROM sc a,sc b WHERE a.sb.s AND a.c1 AND b.c2 AND a.score >b.score;3 --2、查询平均成绩大于60分的同学的学号和平均成绩;4 SELECT student.s,avg(score) FROM student,…

约束流–没有Drools规则语言的现代Java约束

传统上,要使用OptaPlanner进行扩展,您必须学习DRL。 不再。 借助受Java 8 Streams和SQL启发的新Constraints Streams API,您现在可以用Java (或Kotlin或Scala) 编写约束,并且仍然可以从增量计算中受益。 在…

mysql数据库杀掉堵塞_Mysql解决USE DB堵塞详解

遇到故障,我们往往想的是如何解决这个故障,而不是从故障的根本去思考出现这个故障的原因?这样的结果,只能使我们得到了鱼,失去了渔。今天,我们就来分享一个由USE DB堵塞故障引发的思考案例。故障描述今天一…

java拦截器项目应用_使用拦截器分析Java EE应用程序的性能下降/提高

java拦截器项目应用在开发具有某些性能要求的Java EE应用程序时,必须在每个发行版之前验证是否满足这些要求。 您可能会想到,哈德森的一项工作每天晚上在某些特定的硬件平台上执行一系列测试测量。 您可以检查已实现的时间并将它们与给定的要求进行比较…

iis web.config 配置 经典模式_django部署在iis下,webconfig错误

django部署在iis下,webconfig错误错误原因:iis7以后,web.config管理机制更安全了默认情况下,会锁住配置项,不许修改怎么办?如何求解以上问题呢?D:django_websiteshello>%windir%C:Windows 不…

如何在Java中验证电话号码(正则表达式+ Google libphonenumber)

关于如何在不同国家(例如美国,美国)使用Java验证电话号码的快速指南。 带有正则表达式和Google libphonenumber API的示例程序。 1.简介 在本教程中,我们将学习如何在java中验证电话号码 。 这主要是为了验证美国和印度的国家/地…

mysql该账户已存在_mysql 查看函数的所属用户和已存在的函数

复现方式:Delete FROM user Where Usertest and Host%;flush privileges;修复流程:1.用root用户删除两个函数,语句分别为DROP FUNCTION IF EXISTS currval;DROP FUNCTION IF EXISTS nextval;2.然后用程序用户(sharding_slave)创建函数&#x…

joo工作流_不要错过使用jOOλ或jOOQ编写Java 8 SQL单行代码的机会

joo工作流越来越多的人通过为他们的业务采用功能性编程来赶上我们平台的最新更新。 在Data Geekery ,我们将Java 8用于jOOQ集成测试,因为将新的Streams API与lambda表达式一起使用使生成临时测试数据变得非常容易。 但是, 我们并不认为JDK提…

session mysql登录实现_PHP+MYSQL+MYSQL+SESSION实现用户登录的实例

这是我写的用户登录界面。session_start();include(menu2.php);require(configywcl.php);//加载配置文件require(functions.php);?>请登录系统if ($username){$passwordmd5($password);$sql"select * from user where username$username and password$password";…

使用OpenSSL加密,使用Java解密,使​​用OpenSSL RSA公钥

抽象 在2017年,我撰写了一个由三部分组成的系列文章,内容涉及选择最佳的哈希和加密算法。 在对该系列进行研究时,我学到了很多有关哈希和加密的知识。 我学到的最重要的事情是,尽管我必须对如何使用最安全的算法进行自我教育&…

axture动画原型制作_Axure制作原型-基础操作

产品原型从类型可以分为手稿、线框图、低保真、高保真几种效果,在制作的时候分为不同场景来决定我们的输出物类型。比如在会议中为了快速的确定产品规划方向,迅速的记录及表达出当前灵感的碰撞,这个时候通常使用手稿的形式快速绘制&#xff0…

有效Java第三版的源代码已更新为使用较新的功能

那些已经阅读了有效Java 第三版的人可能知道与该书相关的源代码可以在GitHub上获得 。 jbloch / efficiency-java-3e-source-code项目拥有1700多个星星,截至撰写本文时,它已被分叉了近800次。 在有效Java的第三版中, Java的版本主要是JDK 8&a…

mysql 远程连接取消权限_MYSQL远程登录权限设置

Mysql默认关闭远程登录权限,如下操作允许用户在任意地点登录:1. 进入mysql,GRANT ALL PRIVILEGES ON *.* TO root% IDENTIFIED BY WITH GRANT OPTION;IDENTIFIED BY后跟的是密码,可设为空。2. FLUSH privileges; 更新Mysql为了安…