Java 8 Friday:可选将保留为Java中的一个选项

在Data Geekery ,我们喜欢Java。 而且,由于我们真的很喜欢jOOQ的流畅的API和查询DSL ,我们对Java 8将为我们的生态系统带来什么感到非常兴奋。

Java 8星期五

每个星期五,我们都会向您展示一些不错的教程风格的Java 8新功能,这些功能利用了lambda表达式,扩展方法和其他好东西。 您可以在GitHub上找到源代码 。

可选:Java中的新选项


到目前为止,Java 8的所有新增功能让我们非常激动。总而言之,这是一场革命,比以往任何时候都重要。 但是也有一两个疮点。 其中之一就是Java将永远不会真正摆脱

空:十亿美元的错误

在以前的博客文章中,我们已经解释了使用Ceylon语言处理NULL的优点, Ceylon语言找到了解决此问题的最佳解决方案之一-至少在注定永远支持空指针的JVM上。 在Ceylon中,可空性是一个标志,可以通过在类型名称后附加问号来将其添加到每种类型。 一个例子:

void hello() {String? name = process.arguments.first;String greeting;if (exists name) {greeting = "Hello, ``name``!";}else {greeting = "Hello, World!";}print(greeting);
}

真漂亮 结合流敏感的类型 ,您将永远不会再遇到可怕的NullPointerException

最近在手术室里。极客和戳

最近在手术室里。 极客和戳


其他语言也引入了Option类型。

最突出的是:Scala 。

Java 8现在还引入了Optional类型(以及OptionalInt , OptionalLong , OptionalDouble类型-稍后将进一步介绍这些类型)

Optional如何运作?

Optional背后的要点是包装一个Object并提供便利的API以流畅地处理可空性。 这与Java 8 lambda表达式配合得很好,该表达式允许延迟执行操作。 一个例子:

Optional<String> stringOrNot = Optional.of("123");// This String reference will never be null
String alwaysAString =stringOrNot.orElse("");// This Integer reference will be wrapped again
Optional<Integer> integerOrNot = stringOrNot.map(Integer::parseInt);// This int reference will never be null
int alwaysAnInt = stringOrNot.map(s -> Integer.parseInt(s)).orElse(0);

流畅的API,尤其是在新的Java 8 Streams API中具有上述优点,它广泛使用Optional 。 例如:

Arrays.asList(1, 2, 3).stream().findAny().ifPresent(System.out::println);

上面的代码将把Stream中的任何数字打印到控制台上,但前提是存在这样的数字。

未对旧API进行改造

出于明显的向后兼容的原因,“旧API”未进行改装。 换句话说,与Scala不同,Java 8不在JDK上使用Optional 。 实际上,在Streams API中唯一使用Optional地方。 如您在Javadoc中所见,用法非常稀缺:

http://docs.oracle.com/javase/8/docs/api/java/util/class-use/Optional.html

这使Optional难以使用。 之前我们已经写过关于该主题的博客 。 具体而言,API中不存在Optional类型不能保证不可为空。 如果将Streams转换为collections并且将collections转换为streams,这尤其令人讨厌。

Java 8 Optional类型是危险的

参数多态性

Optional对它的“受感染” API的最坏影响是参数多态性,或者简称为:泛型。 当您对类型进行推理时,您将很快理解:

// This is a reference to a simple type:
Number s;// This is a reference to a collection of
// the above simple type:
Collection<Number> c;

泛型通常用于通常被认为是合成的内容。 我们有一个Collection String 。 使用Optional ,会稍微滥用这种组合语义(在Scala和Java中都是如此)来“包装”可能为空的值。 现在,我们有:

// This is a reference to a nullable simple type:
Optional<Number> s;// This is a reference to a collection of 
// possibly nullable simple types
Collection<Optional<Number>> c;

到目前为止,一切都很好。 我们可以替换类型以获得以下内容:

// This is a reference to a simple type:
T s;// This is a reference to a collection of
// the above simple type:
Collection<T> c;

但现在输入通配符和使用地点差异。 我们可以写

// No variance can be applied to simple types:
T s;// Variance can be applied to collections of
// simple types:
Collection<? extends T> source;
Collection<? super T> target;

Optional的上下文中,以上类型是什么意思? 直观地讲,我们希望这与Optional<? extends Number> Optional<? extends Number>Optional<? super Number> Optional<? super Number> 。 在上面的示例中,我们可以编写:

// Read a T-value from the source
T s = source.iterator().next();// ... and put it into the target
target.add(s);

但这对Optional不再起作用

Collection<Optional<? extends T>> source;
Collection<Optional<? super T>> target;// Read a value from the source
Optional<? extends T> s = source.iterator().next();// ... cannot put it into the target
target.add(s); // Nope

…而且,当我们拥有Optional和更复杂的API时,没有其他方法可以推断出使用地点的差异。

如果将通用类型擦除添加到讨论中,情况会变得更糟。 我们不再删除上述Collection的组件类型,而实际上也删除了任何引用的类型。 从运行时/反射的角度来看,这几乎就像在各处使用Object一样!

即使对于简单的用例,泛型系统也非常复杂。 Optional只会使事情变得更糟。 很难将Optional与传统的集合API或其他API融合在一起。 与Ceylon的流敏感键入甚至Groovy的elvis运算符的易用性相比, Optional就像您的大锤。

将其应用于API时要小心!

原始类型

为什么Optional仍然是一个非常有用的添加的主要原因之一是,由于我们还具有OptionalInt , OptionalLong , OptionalDouble类型,因此“对象流”和“原始流”具有“统一的API”。

换句话说,如果您正在使用原始类型,则可以以几乎相同的方式切换流的构造并重用其余的流API使用源代码。 比较这两个链:

// Stream and Optional
Optional<Integer> anyInteger = 
Arrays.asList(1, 2, 3).stream().filter(i -> i % 2 == 0).findAny();
anyInteger.ifPresent(System.out::println);// IntStream and OptionalInt
OptionalInt anyInt =
Arrays.stream(new int[] {1, 2, 3}).filter(i -> i % 2 == 0).findAny();
anyInt.ifPresent(System.out::println);

换句话说,鉴于在JDK API中很少使用这些新类型,因此这种类型在一般情况下的可疑用途(如果改型为非常向后兼容的环境)以及泛型擦除对Optional的影响,我们敢说

真正添加此类型的唯一原因是为引用和原始类型提供更统一的Streams API

太难了 令我们感到疑惑的是,我们是否最终应该完全摆脱原始类型。

哦还有

Optional不是可Serializable

不。 不可Serializable 。 例如,与ArrayList不同。 通常的原因:

在JDK可序列化中进行处理会使我们的维护成本急剧增加,因为这意味着该表示将一直冻结。 这限制了我们将来开发实现的能力,而我们无法轻松修复错误或提供增强功能的情况数量非常之多,而这种情况本来就很简单。 因此,尽管对您来说,这看起来像是一个“可序列化的实现”的简单问题,但不仅限于此。 解决早期的选择以使某些东西可序列化所消耗的工作量是惊人的。

引用Brian Goetz,来自: http : //mail.openjdk.java.net/pipermail/jdk8-dev/2013-September/003276.html

想讨论Optional吗? 在reddit上阅读以下主题:

  • / r / java
  • / r /编程

请继续关注本博客系列中发布的更多令人兴奋的Java 8内容。

翻译自: https://www.javacodegeeks.com/2014/04/java-8-friday-optional-will-remain-an-option-in-java.html

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

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

相关文章

七天开发记录(3)

今天在网上找到了一个开发记账本微信小程序的网址 我看了一下这个APP的源代码&#xff0c;其用分为两个大包。 转载于:https://www.cnblogs.com/zjl-0217/p/10428525.html

TMS320F28335——IO控制/定时计操作

一、实现GPIO控制 1.硬件连接 从电路原理图上看来&#xff0c;LED灯是接在GPIO34 上的。 2.IO设置 2.1设置功能 GPXMUX1/2&#xff1a;功能选择寄存器   GPXMUX1/2 每组 IO 一般有 32 个 IO 口可以配置。GPXMUX1 对应每组的低 16 个 IO 口&#xff0c;GPXMUX2 对应高 16 个…

比Python、Java更快的 Go 语言,能否称霸江湖?

关注之后加星标&#xff0c;江湖要事早知道 ​ 文章来源&#xff1a;jb51.net 有一种语言堪称比语言排行榜前五热门选手的Python、Java更快&#xff0c;它就是GO语言。 Go于2009年11月正式宣布推出&#xff0c;成为开放源代码项目&#xff0c;并在Linux及Mac OS X平台上进行了实…

嗨,您好 。 。 ! 您如何评价Java / Java EE技能?

要知道&#xff0c;就是要知道你一无所知。 那就是真正知识的含义。 苏格拉底 这篇文章旨在为读者提供Java生态系统及其技术堆栈的快速概述。 老实说&#xff0c;从Java EE 7&#xff0c;Java SE 8到Java Embedded 8…&#xff0c;Java平台进行了许多革命性的更改和添加。 哇…

simulinkveristandlabview联合仿真——模型导入搭建人机界面

目录 1.软件版本 2.搭建simulink仿真模型 编译错误 3.导入veristand并建立工程 4.veristand导入labview labview显示veristand工程数据 labview设置veristand工程数据 运行labview工程 1.软件版本 matlab2020a&#xff0c;veristand2020 R4&#xff0c;labview2020 SP…

Java程序员的典型工作过程有哪些_Java程序员都要经历哪些阶段

原标题&#xff1a;Java程序员都要经历哪些阶段程序员从菜鸟到优秀的过程是需要时间&#xff0c;经验&#xff0c;不断的进阶&#xff0c;小编和大家一起看看每个阶段都要经历哪些成长阵痛&#xff1a;没有防卫这个阶段很快就会过去&#xff0c;因为有无数的书本和”前辈”在提…

关于DataFormWebPart中CreatedModifiedInfo信息的分开使用

以下是问题的描述,我先从数据说起.数据存储在一个叫pages的自定义列表中,该列表除默认的栏外,另增加了一栏"Abstract",为多行文本,用于存储文章摘要信息.当该列表中录入数据后如图: 这时,当我们点列表项如"page2"时,会进入该项的 DispForm.aspx页面.如图:这…

Day47 Django基础部分、路由配置、空间名称

1.最简单的路由配置 URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表&#xff1b;你就是以这种方式告诉Django&#xff0c;对于客户端发来的某个URL调用哪一段逻辑代码对应执行。 1.1 例1&#xff1a; 第一步&#xff1a;在…

6-3 向二分搜索树中添加元素 6-4 改进添加操作:深入理解递归终止条件

二分搜索树添加新元素60, 60>41(根节点)&#xff0c;所以一定要插入到41的右子树。 接着在和58比较 1 public class BST<E extends Comparable<E>> {//对于二分搜索树所存储的内容支持泛型&#xff0c;所以在这里写一个E&#xff0c;此外二分搜索树不是支持所有…

ClassNotFoundException:是否减慢了您的JVM?

大多数Java开发人员都熟悉臭名昭著且非常常见的java.lang.ClassNotFoundException 。 虽然通常已经很好地了解了此问题的根源&#xff08;类路径中缺少类/库&#xff0c;类加载器委派问题等&#xff09;&#xff0c;但对整体JVM和性能的影响通常是未知的。 这种情况可能会对您的…

python可以自动写文章吗_让python来告诉你神奇的操作,如何实现文章自动化

三河讲python首先来告诉大家下面的Python程序实现了通过从网页抓取一篇文章&#xff0c;然后根据这篇文章来生成新的文章&#xff0c;这其中的原理就是基于概率统计的文本分析。过程大概就是网页抓取数据->统计分析->生成新文章。网页抓取数据是通过BeautifulSoup库来抓取…

badboy的录制和jmeter的使用

v Jmeter是什么 Apache Jmeter是Apache组织开发的基于Java的压力测试工具。Jmeter可以用于对服务器、网络或对象模拟巨大的负载&#xff0c;来自不同压力类别下测试它们的强度和分析整体性能。另外&#xff0c;Jmeter能够对应用程序做功能、回归测试&#xff0c;通过创建带有断…

一张图看懂offsetX, clientX, pageX, screenX的区别

1.具体含义见下图1 2.浏览器的兼任情况 更多专业前端知识&#xff0c;请上 【猿2048】www.mk2048.com

接口一个被我忽略的地方--接口重定向技术

习惯于用IDE生成接口方法了,右键点击"Implement Interface",生成所有的接口方法声明,还带个Region多方便啊.今天看<<CLR Vir C#>>时才了解到自己是知其然不知其所有然啊. 实现接口方法很简单,新手估计也都会,但怎么理解这个过程,不见得所有人都知道 Base…

vue 学习之路 —— 图片的引入

问题记录&#xff1a;在img中动态设置了src后&#xff0c;图片路径找不到 原因&#xff1a;vue中动态生成的路径无法被url-loader解析到 解决方法&#xff1a; 1、将图片放在static文件夹&#xff0c;然后正常解析 2、将图片使用import方法引入 3、 采用背景图做法&#xff0c;…

跟踪异常–第5部分–使用Spring进行计划

看来我终于快要结束本系列有关使用Spring进行错误跟踪的博客了&#xff0c;对于那些还没有阅读该系列博客的人&#xff0c;我正在编写一个简单但几乎具有工业实力的Spring应用程序&#xff0c;扫描日志文件中的异常&#xff0c;然后生成报告。 在本系列的第一个博客中&#xff…

APP测试理论知识点

什么是APP测试&#xff1f; App测试就是软件工程师对这类应用软件进行功能测试&#xff0c;性能测试&#xff0c;安全性测试以及兼容性测试等。 对于app测试我们一般采用的是黑盒测试方法&#xff0c;也会在必要的时候进行自动化测试以及性能测试&#xff0c;丙炔对于app还会有…

php接口开发 安全_PHP开发api接口安全验证的实例讲解

php的api接口在实际工作中&#xff0c;使用PHP写api接口是经常做的&#xff0c;PHP写好接口后&#xff0c;前台就可以通过链接获取接口提供的数据&#xff0c;而返回的数据一般分为两种情况&#xff0c;xml和json,在这个过程中&#xff0c;服务器并不知道&#xff0c;请求的来源…

Remove Element - LeetCode

目录 题目链接注意点解法小结题目链接 Remove Element - LeetCode 注意点 输入的数组是无序的解法 解法一&#xff1a;使用了erase函数&#xff0c;将等于val的值移除。时间复杂度为O(n) class Solution { public:int removeElement(vector<int>& nums, int val) {fo…

DRF url控制 解析器 响应器 版本控制 分页(常规分页,偏移分页,cursor游标分页)...

url控制第二种写法&#xff08;只要继承了ViewSetMixin&#xff09; url(r^pub/$,views.Pub.as_view({get:list,post:create})), #获取所有记得路由后面加$结束符 #pub/?formatjsonurl(r^pub\.(?P<format>\w)$,views.Pub.as_view({get:list,post:create})), #pu…