为什么我们可以在 Optional.of() 上调用 .orElse()?
Why can we call .orElse() on Optional.of()?
我很好奇为什么可以这样做(至少在 Java 8):
Optional.of(null).orElse("something");
Optional.of(null)
基本上是一个保证的空指针。可以在其上调用 .orElse()
给笨拙的开发人员带来意想不到的漏洞。我一直在四处寻找,看看是否有任何理由这样做。也许这应该解决某些情况?
您可以出于与编写 ((String) null).length()
相同的原因来执行此操作。 Java 编译器有一个静态检查器用于某些事情,例如类型安全,但不检查或拒绝可能抛出 NullPointerException
的代码。如果是这样,代码 throw new NullPointerException();
也不会被允许。
抛出异常的代码通常不会是错误的。虽然静态检查器可以检测到这种情况并发出警告,但如果这是一个错误,那就太糟糕了。某些 IDE 会生成它们自己的关于可能错误的警告,但您必须决定哪些值得检查,哪些不值得检查。
检测这个可能的错误需要一个静态检查器,该检查器是根据 Optional.of
方法的行为知识设计的。 Java Language Specification have made the decision to warn for things like unsafe casts, but not for anything which depends on the semantics of the methods being used. One advantage of this decision is that it means the JLS can be maintained separately from the Java Class Library 文档的作者。
有些语言支持直接在编译器中进行空检查(或者甚至更好的语言根本没有这样的 "thing")- 这已被写入编译器。
javac
不是这样的编译器,坦率地说——我也不希望它变成这样。有些语言的语法如 !
或 ?
或 !?
- 当我阅读这段代码时,它要么对我尖叫,要么问我一些事情(这是我的意见)。
现在,回想一下 Optional
是为 return 类型设计的,因此在您的方法体内您使用了一个 Optional
方法链。如果您 真的 想要检查某些内容是否为空,则 Objects::requireNonNull
- 使用它;如果您不确定某些内容是否为空,您可以使用 Optional::ofNullable
.
我知道并阅读了 Optional::of
和 Optional::ofNullable
的论据,我仍然不喜欢它,我希望它可以只是后者.但是,嘿,人们不必总是同意:我们确实有 Optional::isEmpty
和 Optional::isPresent
。这是一个好的决定吗?我不知道。
与任何其他方法调用一样,您可以将 null
传递给 任何 对象引用,Optional
也不例外。他们能否为 javac
添加语义以仅支持 Optional::of
和 null 检查?大概。有多少人会请求对 和此功能的支持?
Optional.of(null).orElse();
显然上面的代码总是会引发异常。但是:
Optional.of(someMethod()).orElse();
和
Object someMethod() { return null; }
您可能会想:当然,同样的事情。
嗯,其实那是错误的。如果 子类 将 someMethod()
覆盖为 return 一个不同于 null
的值怎么办?!因此,您无法在 compile 时间决定该方法是否 always return null 在 runtime.
长话短说:编译器 可以 在 大量 明显和不太明显的情况下应用各种技术,例如数据流分析,以确定代码 是否会 导致运行时异常。但也有许多其他情况是不可能的。
这里的要点:由定义语言的人来决定他们期望编译器关心什么。
java 人选择了简单 编译器。一个编译速度很快,而且实现起来并不过分复杂的方法。为什么?因为编译器只是简单地避免了过于复杂的检查。
我很好奇为什么可以这样做(至少在 Java 8):
Optional.of(null).orElse("something");
Optional.of(null)
基本上是一个保证的空指针。可以在其上调用 .orElse()
给笨拙的开发人员带来意想不到的漏洞。我一直在四处寻找,看看是否有任何理由这样做。也许这应该解决某些情况?
您可以出于与编写 ((String) null).length()
相同的原因来执行此操作。 Java 编译器有一个静态检查器用于某些事情,例如类型安全,但不检查或拒绝可能抛出 NullPointerException
的代码。如果是这样,代码 throw new NullPointerException();
也不会被允许。
抛出异常的代码通常不会是错误的。虽然静态检查器可以检测到这种情况并发出警告,但如果这是一个错误,那就太糟糕了。某些 IDE 会生成它们自己的关于可能错误的警告,但您必须决定哪些值得检查,哪些不值得检查。
检测这个可能的错误需要一个静态检查器,该检查器是根据 Optional.of
方法的行为知识设计的。 Java Language Specification have made the decision to warn for things like unsafe casts, but not for anything which depends on the semantics of the methods being used. One advantage of this decision is that it means the JLS can be maintained separately from the Java Class Library 文档的作者。
有些语言支持直接在编译器中进行空检查(或者甚至更好的语言根本没有这样的 "thing")- 这已被写入编译器。
javac
不是这样的编译器,坦率地说——我也不希望它变成这样。有些语言的语法如 !
或 ?
或 !?
- 当我阅读这段代码时,它要么对我尖叫,要么问我一些事情(这是我的意见)。
现在,回想一下 Optional
是为 return 类型设计的,因此在您的方法体内您使用了一个 Optional
方法链。如果您 真的 想要检查某些内容是否为空,则 Objects::requireNonNull
- 使用它;如果您不确定某些内容是否为空,您可以使用 Optional::ofNullable
.
我知道并阅读了 Optional::of
和 Optional::ofNullable
的论据,我仍然不喜欢它,我希望它可以只是后者.但是,嘿,人们不必总是同意:我们确实有 Optional::isEmpty
和 Optional::isPresent
。这是一个好的决定吗?我不知道。
与任何其他方法调用一样,您可以将 null
传递给 任何 对象引用,Optional
也不例外。他们能否为 javac
添加语义以仅支持 Optional::of
和 null 检查?大概。有多少人会请求对 和此功能的支持?
Optional.of(null).orElse();
显然上面的代码总是会引发异常。但是:
Optional.of(someMethod()).orElse();
和
Object someMethod() { return null; }
您可能会想:当然,同样的事情。
嗯,其实那是错误的。如果 子类 将 someMethod()
覆盖为 return 一个不同于 null
的值怎么办?!因此,您无法在 compile 时间决定该方法是否 always return null 在 runtime.
长话短说:编译器 可以 在 大量 明显和不太明显的情况下应用各种技术,例如数据流分析,以确定代码 是否会 导致运行时异常。但也有许多其他情况是不可能的。
这里的要点:由定义语言的人来决定他们期望编译器关心什么。
java 人选择了简单 编译器。一个编译速度很快,而且实现起来并不过分复杂的方法。为什么?因为编译器只是简单地避免了过于复杂的检查。