当前位置: 首页 > 知识库问答 >
问题:

为什么Java8是可选的实现为最终的,没有一些和没有层次结构?

吴安和
2023-03-14

在Java中,optional被实现为公共final类optional {...} 而不是somenone的密封层次结构。

为什么这里不是这样?这是Java中缺少sealed的解决方案吗?背后有没有更深层次的推理?

public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
    Objects.requireNonNull(mapper);
    if (!isPresent())
        return empty();
    else {
        return Optional.ofNullable(mapper.apply(value));
    }
}

它们不仅很难看,而且如果有更长的方法链,ispresent将需要在每次调用期间计算,即使optional从一开始就为空。

如果我们可以向下传递一个固定的实现,就可以避免这种情况。

optional
  .map(i -> i) // isPresent()
  .map(Object::toString) // isPresent()
  .map(String::length) // isPresent()
  .map(...) // isPresent()

为什么不使用子类型来建模空和非空的情况?

共有1个答案

长孙作人
2023-03-14

class optional上的final修饰符是为了准备一个更大的特性:值类型,这是Project Valhalla的目标(Java10+的特性)。

您可以在下面链接的2014年文章中阅读关于Java的值类型的所有内容:

JEP169起草了将值对象实现到Java中的建议。

基元类的设计和实现已经足够成熟,我们可以很有信心地预期将Java平台的某些类迁移成未来版本中的基元类。

在2014年的论文中,提到了基于值的类如何充当值类型的盒装版本:

实际上,每个值类型的装箱形式似乎都是一个基于值的类。

但是,理论上,并不是所有的对象都需要标识,正如上面链接的2014年论文中明确提到的:

对象标识仅用于支持可变性,在这种情况下,对象的状态可以发生变化,但保持相同的内在对象。

标识不是自由的,不可变类型不需要变异,这就意味着它们不需要标识。

对象标识具有占用空间和性能成本,这是Java与其他许多面向对象语言不同的一个主要原因,它具有原语。

James Gosling早在1999年就写过一篇关于将不可变类型编译为值的文章:

在当前的语言规范下,一个足够聪明的优化编译器几乎有可能将某些类转换成不是堆分配的、通过值而不是引用传递的轻量级对象:声明类及其所有实例变量为final。

2014年关于Java中的值类型的论文进一步公开了强制执行final要求的决定:

值可以参与基于继承的子类型吗?没有。

值类可以是抽象的还是非final的?没有。

值类型不能参与传统的子类型(如果有的话,那将是有限的)。

 类似资料:
  • 在Java8中,我们有类stream ,奇怪的是,它有一个方法 所以您希望它实现interface Iterable ,这恰恰需要这个方法,但事实并非如此。 当我想使用foreach循环对流进行迭代时,我必须执行如下操作 我是不是漏了什么?

  • 我面临的一些问题,没有收到通知在一些电话。我也不接受GCM的意图。这是我打电话给GCM注册时的日志。在像Nexus和Moto这样的手机上,它运行得非常好。但在Lava和Karbonn这样的低端手机上,我就面临着这个问题。 D/PowerManagerService(649):AcquireWakeLockInternal:lock=1114432392,Flags=0x1,tag=“gcm_con

  • 使用指南 - 数据报告 - 概述 - 为什么有些报告没有权限 在百度统计中,无权限报告所属的站点应是“权限站点”,权限站点在右上角站点选择下拉框中有“权限站点”的字样标注,如图所示: 权限站点是其他账户将其自有站点授权给您查看数据的站点,在授权时定义了您的查看和设置权限。如果此报告无权限,说明授权发起者未授权给您。 您可以在“管理->网站列表”的“权限网站”标签下,查看该站点的权限来源账户,如需开

  • 问题内容: 我正在尝试做这样的事情: 不幸的是,即使在Java 9中也不存在。 为什么它被遗漏了? 建议的解决方法是什么? 问题答案: 为什么它被遗漏了? 该API提供了可重用的构建块。这里的相关积木是,,。通过这些,您可以实现所需的功能:将流内映射到对象,然后获得平面图。提供构建基块的排列是不切实际的,并且很难扩展。 建议的解决方法是什么? 如前所述,使用可用的构建基块(+ ):

  • 许多编译器都提供128位整数类型,但我使用过的编译器都没有提供typedefs。为什么? 据我回忆,标准 用于此目的的储量 鼓励提供此类类型的实现提供typedef 要求此类实现提供至少128位的intmax_t (而且,我不相信我使用了实际上符合最后一点的实现)

  • 问题内容: 当我使用pip时,没有sudo通常不会起作用。我经常看到人们在不使用sudo的情况下使用pip,所以我在做什么错呢? 我读到不建议使用sudo安装pip软件包。我知道可以不用sudo使用pip,但是要安装,我必须先使用sudo。 当我尝试不使用sudo安装pip时,我得到: 尝试通过以下方式安装flask时: 问题答案: 在Unix / Linux系统中用于在另一个用户中使用 其 权限