为什么猫王不应该访问Java

最近,我参与了一个关于Java的Optional类型系统的漫长的Twitter讨论 ,该系统区分可空类型和非可空类型以及Elvis运算符 ,该运算符允许选择空值安全的成员。 后者被认为是简洁的null处理的杀手级功能,对此我强烈不同意。

我对此的看法是,如果没有允许每个类型都不能为空的类型系统(Java不久将不会发生这种情况),Elvis运算符将不利于正确性和可读性。

让我解释一下原因。

零的症结

null的问题在于它没有说明为什么缺少值

我以前已经写过这个 。 null的问题在于它会导致异常-只是一种症状。 null的问题在于它没有说明为什么缺少该值。 是否尝试过并且失败了(例如连接到数据库),但是由于某种原因,执行仍在继续? 是否有许多值(可能是一对?),其中只能出现一个? 值是否像非强制性的用户输入一样是可选的? 或者,最后,这是一个实际的实现错误,并且该值真的应该永远不会丢失吗?

错误的代码将所有这些情况映射到同一件事:null。 因此,当NullPointerException或其他与缺失值相关的不良行为(“为什么此字段为空?”,“为什么搜索找不到该东西?”)弹出时,解决该问题的第一步是什么? 找出为什么缺少该值以及该值是否正确或实现错误。 实际上,回答该问题通常是解决方案的90%!

但是,这样做非常困难,因为null可以隐藏在任何引用类型中,并且除非进行了严格的检查(例如在构造函数和方法参数上使用Objects :: requireNonNull),否则它很容易在整个代码库中扩散。 因此,在回答为什么null在引起问题的地方出现之前,有必要先将其跟踪到其来源,这在一个足够复杂的系统中可能会花费很多时间。

因此,null的根本问题不是它引起的不当行为,而是将各种不同的关注点混为一个单一的,特别是偷偷摸摸且容易出错的概念。

由Kevin Dooley在CC-BY 2.0下发布

猫王进入大楼

我最近与Kotlin一起玩耍,对空值处理感到惊讶,就像我以为我会从阅读它开始一样。 它不是唯一以这种方式执行的语言,而是我实际使用的语言,因此我以它为例。 但这仅仅是:一个例子。 这不是“ Kotlin比Java更好”的说法,而是“看看其他类型系统如何处理此问题”的阐述。

(如果您想进一步了解Kotlin的类型系统,我强烈建议您进行全面介绍 。)

无论如何,在这种类型的系统中,默认引用是不可为空的,并且编译器确保不会发生任何意外。 字符串始终是字符串,而不是“字符串或null”。

// declare a variable of non-nullable type `User`
val user : User = ...
// call properties (if you don't know the syntax,
// just assume these were public fields)
val userStreet : String = user.address.street
// if neither `address` not `street` return a nullable type,
// `userStreet` can never be null;
// if they would, the code would not compile because `userStreet`
// is of the non-nullable type `String`

当然,事情可能会丢失,并且可以通过追加使每种类型都为空。 对它。 从这一点开始,由于空引用,成员访问(例如调用方法)存在失败的风险。 令人敬畏的是,编译器意识到了风险,并迫使您正确地处理风险(或者大打折扣,以克服抱怨)。 做到这一点的一种方法是什么? 猫王操作员!

Elvis,写为?,区分成员所引用的引用是否为空。 如果为null,则不调用该成员,整个表达式的计算结果为null。 如果存在,则按预期方式调用该成员。

// declare a variable of the nullable type `User`
val user : User? = ...
// use Elvis to navigate properties null-safely<
val userStreet : String? = user?.address?.street
// if `user` is null, so is `userStreet`;
// `address` and `street` might return nullable types

在了解可空性的类型系统中,猫王是一种很棒的机制! 使用它,您可以表示自己知道值可能会丢失,并接受此结果作为调用结果。

同时,编译器将强制您在可能为空的引用上使用它,从而防止意外的异常。 此外,它将强行将丑陋的nullability-property传播给您将结果分配给的变量。 这迫使您随身携带可能为null值的复杂性,并且有激励您尽早摆脱它。

为什么这在Java中不起作用?

猫王只适用于非空类型
因此,如果我在Kotlin中非常喜欢Elvis,为什么不希望在Java中看到它? 因为猫王只能与区分可空类型和不可空类型的类型系统一起使用! 否则,它的作用与预期相反,并且使null问题变得更加棘手。

想一想:通过在null上调用成员可以得到NPE。 最简单的事情是什么? 挤在那里的问号,并完成它!

那是对的吗? Null不会告诉您是否允许丢失值,那么谁知道呢? 它会对调用或被调用代码产生负面影响吗? 好吧,编译器无法告诉您该代码是否可以处理null,那么又有人知道吗?

像Kotlin的类型系统可以回答这两个问题,而Java会让您猜测。 正确的选择是调查,这需要付出努力。 错误的选择是只扩散null。 如果第二种选择比今天简单得多,您认为会发生什么? 您是否希望看到或多或少缺少值的问题? 您是否期望从null引用的源到导致问题变得更长或更短的路径?

猫王让错误的选择变得容易

好的语言和好的API使正确的选择变得容易。 良好的静态类型系统中设计良好的类型可以排除运行时不应发生的情况。 这两个帐户上的Java猫王都将失败。 与其要求一种更简单的方法来处理null,不如最好从代码库或至少每种类型的public API中 消除它 。

一言以蔽之

Twitter上的大多数讨论实际上都是围绕Optional但在这里我不再重复,因为那是另一篇文章( 我已经写过一遍, 实际上是两次 )。 相反,我想强调一个特定的论点并将其置于猫王的语境中。

有人反复指出,这是Optional的弱点,它很容易被误操作,使用不谨慎是一种可能甚至是普遍的情况。 就个人而言,我还没有那个问题,但这听起来很合理。 我认为可以通过适度的努力(肯定比正确的空值处理更容易)来学习处理Optional但是除非发生这种情况,否则我会明白滥用它会导致代码库变糟。

但是对于那些有这种想法的人,我想提出一个问题:您到底认为猫王的情况不会这么糟吗? 正如我在上文中指出的那样,这使可怕的选择变得非常简单! 可以说比Optional所能做到的更多。

摘要

缺乏必要的邪恶观念。 编码为null不好。 扩散可怕。

如果Java有一个类型系统可以帮助处理null并激励人们远离它,那么猫王会很棒。 ,不是。 因此,更容易在代码库中散布null而不是为丢失的值创建适当的设计,从而使针向错误的方向移动。

最后,打个招呼:如果您已经读完所有这些,并且仍然想要Elvis,因为它会使您的生活变得更加轻松 ,那么您的API可能设计不当,因为它们过度使用了null。 在那种情况下,您渴望接触Elvis的愿望正是我认为Java不应该拥有它的原因。

翻译自: https://www.javacodegeeks.com/2017/02/elvis-not-visit-java.html

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

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

相关文章

python a and b_python-尽管Numpy建议a.b,为什么a.dot(b)比a @ b更...

根据question的答案,也根据numpy的答案,与a.dot(b)相比,二维数组的矩阵乘法最好通过a b或numpy.matmul(a,b)完成.If both a and b are 2-D arrays, it is matrix multiplication, but usingmatmul or a b is preferred.我做了以下基准测试,发现相反的结果.问题&#xff1a;我的…

Mysql高可用集群-解决MMM单点故障

目录 一.理论概述组件介绍三.部署四.测试五.总结preface: MMM架构相比于MHA来说各方面都逊色不少,写这篇案例也算是整理下思路吧. 一.理论概述 MMM(Master-Master replication Manager for MySQL) 是一套支持双主日常管理的脚本程序,使用Perl语言开发,主要用来监控和管理MySQL双…

vector元素的读取

1通过下标&#xff1a; int a[6] { 1,2,3,4,5,6 }; vector<int> b(a, a 4); for (int i 0; i < b.size() - 1; i) cout << b[i] << " "; 2通过迭代器 int a[6] { 1,2,3,4,5,6 }; vector<int> b(a, a 4); for (vector<int>:…

vector 中的元素去重

#include<iostream> #include<vector> #include<algorithm> using namespace std; int main() { cout << "********************一维向量*************************" << endl; vector<int> a; for (int i 0; i < 6; i) …

tcp的3次握手4次挥手

转载于:https://www.cnblogs.com/georgexu/p/10909808.html

python 如何定义字典_python dict如何定义

1.字典的定义字典的格式&#xff1a;字典名 {key1:value1, key2:value2,...}字典是无序的&#xff0c;是可变的数据类型字典的key不能是可变的数据类型(列表 字典)字典的key是不能重复的&#xff0c;但value可以例&#xff1a;my_dict {"name": "小明", …

MS SQL JSON类型type

在MS SQL Server 2016&#xff0c;已经支持JSON处理。 执行下面代码&#xff0c;将获取ms sql server对象类型以及其说明: IF OBJECT_ID(tempdb.dbo.#json_type) IS NOT NULL DROP TABLE #json_typeCREATE TABLE #json_type ( [type] TINYINT,[data_type] NVARCHAR(30) ) IN…

Eigen(8)实例最小二乘法

用Eigen库解Axb线性方程&#xff0c;使用最小二乘法 #include <iostream>#include <Eigen/Dense>using namespace std;using namespace Eigen;int main(){//对方程AxbMatrixXf A MatrixXf::Random(3, 2);std::cout << "Here is the matrix A:\n"…

java 和javafx_JavaFX 2 XYCharts和Java 7功能

java 和javafx我最喜欢的JavaFX 2功能之一是它在javafx.scene.chart包中提供的标准图表。 该软件包提供了几种不同类型的现成图表。 除其中之一&#xff08; PieChart &#xff09;外&#xff0c;所有其他均为“ 2轴图”&#xff08; XYChart的特定实现&#xff09;。 在本文中…

python语句分为什么语句_在python中如何分句

在处理文本时&#xff0c;会遇到需要将文本以 句子 为单位进行切分(分句)的场景&#xff0c;而文本又可以分为 中文文本 和 英文文本 &#xff0c;处理的方法会略有不同。本文会介绍 Python 是如何处理 分句 的。分句的关键是找到合适的结束符号&#xff0c;比如&#xff1a;中…

Spring框架(二) ---- bean的歧义性

自动装配bean时&#xff0c;如果符合条件的bean超过一个&#xff0c;就会出现歧义性&#xff0c;抛出NoUniqueBeanDefinitionException异常&#xff0c;有如下两种方法保证bean的唯一性&#xff1a; 一、使用Primary注解标记首选bean 1.与Component注解组合使用在自动扫描的bea…

Eigen(7)Map类

这里将解释Eigen如何与原生raw C/C 数组混合编程。 1. 简介 Eigen中定义了一系列的vector和matrix&#xff0c;相比copy数据&#xff0c;更一般的方式是复用数据的内存&#xff0c;将它们转变为Eigen类型。Map类很好地实现了这个功能。 2. Map类型 Map的定义 Map<Matrix&…

从战中清理代码

从战中清除代码–验证 让我们直接从一个例子开始。 考虑一个简单的Web服务&#xff0c;该服务允许客户向商店下订单。 订单控制器的非常简化的版本可能如下所示– RestController RequestMapping(value "/",consumes MediaType.APPLICATION_JSON_VALUE,produces …

python opencv屏幕找图_使用Python+OpenCV进行图像模板匹配(Match Template)实例-找到百度首页按钮并点击...

意图&#xff1a;准备一张小图&#xff0c;在电脑屏幕上找到小图坐标&#xff0c;并点击。1 安装 opencv 和 numpy&#xff1a;pip3 install opencv-python上述命令将 opencv 和 numpy都安装了&#xff0c;可以在类似D:\Python36\Lib\site-packages目录下看到2 准备小图&…

Eigen(6)快操作

1. 块操作 块是matrix或array中的矩形子部分。 2. 使用块 函数.block()&#xff0c;有两种形式 operation 构建一个动态尺寸的block 构建一个固定尺寸的block 起点(i,j)块大小(p,q) .block(i,j,p,q) .block< p,q >(i,j) Eigen中&#xff0c;索引从0开始。 两个版本…

11.【原创】chrom文件上传后,手动释放内存

最近在用google chrom测试大文件上传功能&#xff0c;上传的文件为4GB左右的。但是试了几次之后突然发现&#xff0c;我C盘的内存由原先的剩余的30多GB变为了15GB左右&#xff0c;猜想是chrom文件上传之后并没有把读取出的文件进行清理。网上找了很久也没有找到类似解决方法。于…

mapreduce排序算法_MapReduce算法–二级排序

mapreduce排序算法我们将继续执行有关实现MapReduce算法的系列文章&#xff0c;该系列可在使用MapReduce进行数据密集型文本处理中找到。 本系列的其他文章&#xff1a; 使用MapReduce进行数据密集型文本处理 使用MapReduce进行数据密集型文本处理-本地聚合第二部分 使用Had…

数据图表与分析图_几种可视化数据分析图表的使用

图表简洁大方、一目了然&#xff0c;利用图表工具就能轻松实现&#xff0c;是数据分析中常采用的方式。今天利用在雀书无代码平台搭建的图表来介绍几种常见数据分析图表的使用。1. 柱状图柱状图可以显示一段时间内的数据变化或显示各项之间的比较情况&#xff0c;主要使用颜色进…

java打包exe

配置如下&#xff1a; 1&#xff0c;复制运行环境jre&#xff1b; 2&#xff0c;复制项目配置文件config; 3&#xff0c;复制项目运行的lib包&#xff1b; 4&#xff0c;编写清单文件&#xff0c;放到系统目录&#xff1b; 5&#xff0c;将项目打包成xxx.jar&#xff0c;放入到…

Eigen(5)Array类和元素级操作

0. 为什么使用Array 相对于Matrix提供的线性代数运算&#xff0c;Array类提供了更为一般的数组功能。Array类为元素级的操作提供了有效途径&#xff0c;比如点加&#xff08;每个元素加值&#xff09;或两个数据相应元素的点乘。 1. Array Array是个类模板&#xff08;类似于M…