我已经阅读了很多有关应该使用Optional
的情况的信息。
我读过的很多页面都说Optional
不应用于私有实例变量,而应由getter返回。
我本以为将私有实例变量作为可选变量仍然有用。如果有人查看我的代码,他们可以看到值可以为空,而不必检查文档以查看是否可以返回null。
在Scala中,从不使用null,只有在与Java互操作的情况下才使用null。如果值可以为null,建议始终使用可选值。这种方法对我来说更有意义。
这是一个提及它的页面:
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的返回类型之前,您不知道邮政编码可以为null。如果您不熟悉该代码,则可能会错过此添加操作,从而扩展了类,从而导致空指针异常。
这是一个有关Scala的Option
的问题。
为什么Java和Scala在可选选项如何使用方面有区别?
答案 0 :(得分:9)
并非所有Java开发人员都同意您所描述的方法。请检查龙目岛的创建者post。
我猜想在Java中使用Optional
的另一种方法的原因是Java社区直到Java 8都没有它,因此大多数人习惯了 null 。一方面,许多新的API(例如findAny
中的Stream
)返回Optional
,但仍有许多标准库方法仅返回 null ,因此您始终必须记住用Optional.ofNullable
包装函数调用,或者检查值是否不为空。
Optional
已添加到Java 8,但不鼓励将其用作类字段,因为Optional
未实现Serializable
(许多人将Java的序列化用作默认序列化引擎)框架或系统(如Akka,Spark,Kafka等)。
另一方面,Option
与Scala标准库紧密绑定。
据我所知,没有Scala的标准库API返回 null ,但是返回Option
,不建议在您的Scala代码中完全使用 null 。您甚至可以将您的项目配置为如果 null 为used,则编译失败。
Option
也是Serializable
,其通常的做法是将其用作可以为空的值的类字段。
如果您想在Java代码中使用类似的方法,请检查 Vavr 中的Option。它是可序列化的,因此可以安全地用作字段,并且还具有两个子类None
和Some
(类似于Scala的Option
),因此可以在Vavr的模式匹配中使用:< / p>
Match(option).of(
Case($Some($()), "defined"),
Case($None(), "empty")
);
答案 1 :(得分:5)
在Scala中,Option已紧密集成到该语言的API中。
代表可选值。 Option的实例是scala的实例。Some或对象None。 使用scala.Option实例的最惯用方式是将其视为集合或monad,并使用map,flatMap,filter或foreach。
从上面的引用中可以看到,这里没有null
的解释,因为它应该用作mondad或集合。
在Java中,Optional用于将NullPointerException情况用于以下情况,从而使我们免于崩溃:
可能包含也可能不包含非null值的容器对象。如果存在值,则isPresent()将返回true,而get()将返回该值。
一种编程语言,它通过使用Kotlin来非常清楚地向用户显示变量是否可以为null,并且显示出编译错误:
var a: String = "abc"
a = null // compilation error
var b: String? = "abc"
b = null // ok
print(b)
答案 2 :(得分:3)
与Stream类似,Optional是一个迭代的«event»类,不适合用作“真实”对象中的字段。
然后就是无法序列化的缺点(可能会解决)。
但是我认为基数0和1的某些变量可能是可选。
就像 list 一样有效。使用List
字段的趋势是(恕我直言),它最初不允许为空,而是始终具有(空)列表。
在相同的编码样式中,Optional
确保仅使用安全访问,尤其是可以以链接样式进行映射:
Optional<TextField> t = ...
String s = t.map(t::getText).orElse("N/A");
Optional<String> u = t.map(t::getText);
t.ifPresent(s -> { ... });
特别是ifPresent
确保不会意外地使用null。
可选是有价值的规范。
答案 3 :(得分:-1)
不对实例变量使用Optional
的一个原因是Optional
引用本身很容易成为null
。这违反了Optional
周围的隐含合同,即您永远都不应创建或遇到null
对Optional
的引用。
class Foo {
Optional<Bar> bar;
}
Foo f = new Foo();
if (f.bar.isPresent()) { // NullPointerException
...
}
这是在Java中使用Optional
字段创建类的最简单方法。从某种意义上说,这种语言鼓励您编写这样的代码。
另一方面,在Scala中,定义Foo
的最简单方法是
case class Foo(bar: Option[Bar])
这很容易
case class Foo(bar: Option[Bar] = None)
两者都避免使用NPE。