首页 > 解决方案 > 为什么不可选用于实例变量?

问题描述

我一直在阅读很多关于Optional应该使用的案例。

我读过的很多页面都说Optional不应该用于私有实例变量,而应该由 getter 返回。

我原以为将私有实例变量作为可选变量仍然很有用。如果有人查看我的代码,他们可以看到一个值可以为空,而不必检查文档以查看是否可以返回 null。

在 Scala 中,null 从不使用,只是为了与 Java 进行互操作。如果值可以为空,建议始终使用可选项。这种方法对我来说更有意义。

这是一个提到它的页面:

https://blog.joda.org/2015/08/java-se-8-optional-pragmatic-approach.html

这是示例代码。

private final String addressLine;  // never null
private final String city;         // never null
private final String postcode;     // optional, thus may be null

// normal getters
public String getAddressLine() { return addressLine; }
public String getCity() { return city; }

// special getter for optional field
public Optional<String> getPostcode() {
  return Optional.ofNullable(postcode);
}

我能看到的唯一优点是,如果你想序列化对象,现在可以,因为它没有将可选存储在变量中。

缺点是在检查 getter 的返回类型之前,您不知道 postcode 可能为 null。如果您不熟悉代码,您可能会错过这个添加扩展类,从而导致空指针异常。

这是一个关于 Scala 的问题Option

何时使用选项

为什么 Java 和 Scala 在应该如何使用 optional 方面存在差异?

标签: javascalaoptional

解决方案


并非所有 Java 开发人员都同意您描述的方法。请查看 Lombok 的创建者的这篇文章

我猜想在 Java 中使用不同方法的原因Optional是 Java 社区在 Java 8 之前一直没有它,所以大多数人习惯于null。一方面,很多新的 API(比如findAnyfrom Stream)返回Optional,但仍然有很多标准库方法只返回null,所以你总是必须记住要么包装你的函数调用,Optional.ofNullable要么检查值是否不为 null。

Optional已添加到 Java 8,但不鼓励将其用作类字段,因为Optional它没有实现Serializable(并且 Java 的序列化被许多框架或系统(如 Akka、Spark、Kafka 等)用作默认序列化引擎)。

另一方面Option,它与 Scala 标准库的绑定非常紧密。据我所知,没有 Scala 的标准库 API 返回null , 但是Option,并且不鼓励在 Scala 代码中使用null 。您甚至可以配置您的项目,如果使用null,它将无法编译。

Option也是Serializable,其通常使用的做法是作为可以为空的值的类字段。

如果您想在 Java 代码中使用类似的方法,请检查Vavr中的选项。它是可序列化的,因此可以安全地用作字段,并且它还有两个子类和(类似于 Scala 的),因此可以在 Vavr 的模式匹配中使用:NoneSomeOption

Match(option).of(
    Case($Some($()), "defined"),
    Case($None(), "empty")
);

推荐阅读