在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中的一个选项相关推荐

  1. 用Java实现猜数游戏:在程序中预设一个0-9之间的整数,让用户通过键盘输入所猜的数,如果大于预设的数,显示“遗憾,太大了” ;小于预设的数,显示“遗憾,太小了” ,如此循环,直至猜中该数,

    猜数游戏 在程序中预设一个0-9之间的整数,让用户通过键盘输入所猜的数,如果大于预设的数,显示"遗憾,太大了" ;小于预设的数,显示"遗憾,太小了" ,如此循环 ...

  2. java个十百千万位余数_java中求一个整数个十百千位的方法

    展开全部 主要的思想是先将这个整数对10求余,636f707962616964757a686964616f31333337396333得到个位数,再将整数除以10得到个位数以外的其余数(除以10之后因 ...

  3. 一个Java 程序的主方法_java application程序中,每一个类中,必有一个主方法main()方法。...

    [多选题]518.电视作品情节结构有() [多选题]下列少数民族中,( )的住房形式多为干栏式建筑. [单选题]21.教师埋头备课,突然站起来,下一镜头就可接教师站着在讲台上讲课,这是( ). [判断 ...

  4. java注解返回不同消息,Spring MVC Controller中的一个读入和返回都是JSON的方法如何获取javax.validation注解的异常信息...

    Spring MVC Controller中的一个读入和返回都是JSON的方法怎么获取javax.validation注解的错误信息? 本帖最后由 LonelyCoder2012 于 2014-03- ...

  5. 用java画网状图_如何在背景中绘制一个带网格线的漂亮条形图?

    我是Matlab的新手 . 我做了一个实验 . 我需要帮助将结果绘制在2条形图(具有不同颜色)中,结果图形需要有网格线 . 有人建议使用非常matlap的代码输出一个漂亮的情节吗? 数据如下: x轴是 ...

  6. java 画三角形_java – 如何在Android画布中绘制一个填充三角形?

    所以我正在绘制这个三角形在Android地图使用下面的代码在我的绘制方法: paint.setARGB(255, 153, 29, 29); paint.setStyle(Paint.Style.FI ...

  7. java 初始化和清楚_浅谈Java中的初始化和清理

    引言 这篇文章我们主要介绍Java初始化和清理的相关内容,这些内容虽然比较基础,但是还是在这边做一个简单的总结,方便以后查阅. 初始化过程 Java尽力保证:所有变量在使用之前都会得到恰当的初始化(对 ...

  8. java 创建用户界面_建立图形用户界面 JAVA实验

    实验 7 建立图形用户界面 一.实验目的 了解图形用户界面基本组件窗口.按钮.文本框.选择框.滚动条等的使用方法,了解如何使用布局管理器对组件进行管理,以及如何使用 Java 的事件处理机制. 二.实 ...

  9. java反射api研究_深入研究Java 8中的可选类API

    java反射api研究 作为Java程序员,我们所有人都经历了以下情况:我们调用一个方法来获取某个值,然后代替直接对返回值调用某些方法,我们首先必须检查返回值是否不为null,然后在返回值. 这是像G ...

最新文章

  1. JZOJ 1277. 最高的奶牛
  2. 嵌入式linux系统下简单守护进程(daemon)的编写
  3. 如何使用悲观锁定修复乐观锁定竞争条件
  4. pat 乙级 1028 人口普查(C++)
  5. 【代码刷题】排序算法总结(python实现)
  6. Nginx的执行阶段详解
  7. mac 下开发golang 配置
  8. 最后2天,错过等1年,这7本计算机经典图书竟然打折了!
  9. 北上广等一线城市 IT 岗位已接近饱和?
  10. Tomcat服务安全加固和优化
  11. 【Linux_Fedora_应用系列】_1_如何安装音乐播放器和mp3解码
  12. stm32之神州三号开发板 USB DFU 实现过程
  13. CSS3简易表盘时钟
  14. leetcode 58. 最后一个单词的长度(Length of Last Word)
  15. 华为鸿蒙理性,华为的理性 鸿蒙的节奏
  16. picker多选 vant_vant的Picker 选择器
  17. Android:安卓学习笔记之共享元素的简单理解和使用
  18. qsort 函数的使用
  19. Haxe FD 开发学习
  20. 射频识别RFID:七个问题 让你看透RFID

热门文章

  1. maven的三种packaging方式
  2. 历年安徽省二计算机考试题库,2010安徽省计算机等级考试试题 二级ACCESS最新考试试题库...
  3. 不同范数下的余弦定理_第06题 | 从源头追溯「余弦定理」amp; 文理科知识点的异同...
  4. 转:centos8开启防火墙端口
  5. 自定义类加载器(ClassLoader + URLClassLoader)
  6. 关于Object.clone克隆方法的测试
  7. Spring IOC 如何解决循环依赖?
  8. Zookeeper入门总结
  9. vim 命令模式 筛选_10个步骤的筛选器模式
  10. s71200模拟量输入输出_模拟用户输入并检查输出的简单方法