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
Java 8 Friday:可选将保留为Java中的一个选项相关推荐
- 用Java实现猜数游戏:在程序中预设一个0-9之间的整数,让用户通过键盘输入所猜的数,如果大于预设的数,显示“遗憾,太大了” ;小于预设的数,显示“遗憾,太小了” ,如此循环,直至猜中该数,
猜数游戏 在程序中预设一个0-9之间的整数,让用户通过键盘输入所猜的数,如果大于预设的数,显示"遗憾,太大了" ;小于预设的数,显示"遗憾,太小了" ,如此循环 ...
- java个十百千万位余数_java中求一个整数个十百千位的方法
展开全部 主要的思想是先将这个整数对10求余,636f707962616964757a686964616f31333337396333得到个位数,再将整数除以10得到个位数以外的其余数(除以10之后因 ...
- 一个Java 程序的主方法_java application程序中,每一个类中,必有一个主方法main()方法。...
[多选题]518.电视作品情节结构有() [多选题]下列少数民族中,( )的住房形式多为干栏式建筑. [单选题]21.教师埋头备课,突然站起来,下一镜头就可接教师站着在讲台上讲课,这是( ). [判断 ...
- java注解返回不同消息,Spring MVC Controller中的一个读入和返回都是JSON的方法如何获取javax.validation注解的异常信息...
Spring MVC Controller中的一个读入和返回都是JSON的方法怎么获取javax.validation注解的错误信息? 本帖最后由 LonelyCoder2012 于 2014-03- ...
- 用java画网状图_如何在背景中绘制一个带网格线的漂亮条形图?
我是Matlab的新手 . 我做了一个实验 . 我需要帮助将结果绘制在2条形图(具有不同颜色)中,结果图形需要有网格线 . 有人建议使用非常matlap的代码输出一个漂亮的情节吗? 数据如下: x轴是 ...
- java 画三角形_java – 如何在Android画布中绘制一个填充三角形?
所以我正在绘制这个三角形在Android地图使用下面的代码在我的绘制方法: paint.setARGB(255, 153, 29, 29); paint.setStyle(Paint.Style.FI ...
- java 初始化和清楚_浅谈Java中的初始化和清理
引言 这篇文章我们主要介绍Java初始化和清理的相关内容,这些内容虽然比较基础,但是还是在这边做一个简单的总结,方便以后查阅. 初始化过程 Java尽力保证:所有变量在使用之前都会得到恰当的初始化(对 ...
- java 创建用户界面_建立图形用户界面 JAVA实验
实验 7 建立图形用户界面 一.实验目的 了解图形用户界面基本组件窗口.按钮.文本框.选择框.滚动条等的使用方法,了解如何使用布局管理器对组件进行管理,以及如何使用 Java 的事件处理机制. 二.实 ...
- java反射api研究_深入研究Java 8中的可选类API
java反射api研究 作为Java程序员,我们所有人都经历了以下情况:我们调用一个方法来获取某个值,然后代替直接对返回值调用某些方法,我们首先必须检查返回值是否不为null,然后在返回值. 这是像G ...
最新文章
- JZOJ 1277. 最高的奶牛
- 嵌入式linux系统下简单守护进程(daemon)的编写
- 如何使用悲观锁定修复乐观锁定竞争条件
- pat 乙级 1028 人口普查(C++)
- 【代码刷题】排序算法总结(python实现)
- Nginx的执行阶段详解
- mac 下开发golang 配置
- 最后2天,错过等1年,这7本计算机经典图书竟然打折了!
- 北上广等一线城市 IT 岗位已接近饱和?
- Tomcat服务安全加固和优化
- 【Linux_Fedora_应用系列】_1_如何安装音乐播放器和mp3解码
- stm32之神州三号开发板 USB DFU 实现过程
- CSS3简易表盘时钟
- leetcode 58. 最后一个单词的长度(Length of Last Word)
- 华为鸿蒙理性,华为的理性 鸿蒙的节奏
- picker多选 vant_vant的Picker 选择器
- Android:安卓学习笔记之共享元素的简单理解和使用
- qsort 函数的使用
- Haxe FD 开发学习
- 射频识别RFID:七个问题 让你看透RFID
热门文章
- maven的三种packaging方式
- 历年安徽省二计算机考试题库,2010安徽省计算机等级考试试题 二级ACCESS最新考试试题库...
- 不同范数下的余弦定理_第06题 | 从源头追溯「余弦定理」amp; 文理科知识点的异同...
- 转:centos8开启防火墙端口
- 自定义类加载器(ClassLoader + URLClassLoader)
- 关于Object.clone克隆方法的测试
- Spring IOC 如何解决循环依赖?
- Zookeeper入门总结
- vim 命令模式 筛选_10个步骤的筛选器模式
- s71200模拟量输入输出_模拟用户输入并检查输出的简单方法