什么时候不使用Java中的optionals

什么是可选的?(What are Optionals?)

Optionals have been introduced in Java 8. This concept is borrowed from other languages. Primarily from languages of functional nature like Haskell, F# etc. Optional is a container object which may or may not contain a non-null value.

Java 8中引入了可选选项。该概念是从其他语言中借用的。 主要来自功能性质的语言,例如Haskell,F#等。可选的容器对象可以包含也可以不包含非null值。

为什么要使用它? (Why using it?)

Let’s have a look at this example where we want to get name of a book retrieved from database:

让我们看一下这个例子,我们要从数据库中获取一本书的名称:

Book book = bookRepository.findById(id);
String bookName = book.getName();

This code will compile just fine and nothing will not tell you that there is a huge problem. We forgot to check for null. We need to fix this ASAP before someone pushed this code to Production:

这段代码可以很好地编译,并且什么也不会告诉你这是一个巨大的问题。 我们忘记检查是否为空。 在有人将此代码推送到生产环境之前,我们需要尽快解决此问题:

Book book = bookRepository.findById(id);
String bookName;
if (book != null) {
bookName = book.getName();
}

Java syntax is not able to help us to identify those places where we unintentionally forgot to place a null-check. This is where Optional might be handy. This is how we can rewrite our example using Optionals:

Java语法无法帮助我们识别那些我们无意间忘记进行空检查的地方。 这是可选的方便之处。 这是我们可以使用Optionals重写示例的方式:

Optional<Book> bookOptional = bookRepository.findById(id);
String bookName = bookOptional.getName(); // We can't do this!
// the line above produces compilation error

Perfect! Java is able to tell us that there is one step that we’re missing:

完善! Java能够告诉我们,我们缺少一个步骤:

String bookName = bookOptional.get().getName();

Again this is still prone to null reference exceptions but at least that extra step that involves using a helper method get(). This extra step is able to remind a developer that there is the case where bookOptional can be null and we need to handle such scenarios.

同样,这仍然容易导致null引用异常,但至少需要使用辅助方法get()的额外步骤。 这个额外的步骤可以提醒开发人员,在某些情况下bookOptional可以为null ,我们需要处理这种情况。

Optional<Book> bookOptional = bookRepository.findById(id);
String bookName;
if (!bookOptional.isEmpty()) {
Book book = bookOptional.get();
String bookName = book.getName();
}

Seems like we have the magic potion and we can use Optionals everywhere and null reference exceptions will just go away. Unfortunately it’s not that straightforward. The problem that we have that Optionals bloat our code. In Haskell, F# and other programming languages there are built in language constructs that help you utilise the concept of Optionals. And it looks concise and comprehensive there. In Java you have to use helper methods get() and isPresent() repeatedly to achieve the same outcome.

似乎我们拥有神奇的魔力,并且我们可以在任何地方使用Optionals,并且null引用异常将消失。 不幸的是,这并不是那么简单。 我们的问题使Optionals膨胀了我们的代码。 在Haskell,F#和其他编程语言中,内置了语言构造,可帮助您利用Optionals的概念。 那里看起来简洁而全面。 在Java中,必须重复使用辅助方法get()isPresent()才能获得相同的结果。

可读性问题 (Readability issue)

Consider this scenario where we need to build a shelf of book authors.

考虑这种情况,我们需要建立书架。

public Shelf buildShelf(Book book) {
Shelf shelf = new Shelf();
if (book.getAuthorId().isPresent()) {
long authorId = book.getAuthorId().getAsLong();
Optional<Author> authorOptional = repository.findById(authorId);
if (authorOptional.isPresent() && authorOptional.get().getName().isPresent()) {
Author author = authorOptional.get();
String authorName = author.getName().get();
shelf.addAuthorName(authorName);
}
}
return shelf;
}

Let’s have a look at the same version of the code without using optionals:

让我们看一下相同版本的代码,而不使用可选参数:

public Shelf buildShelf(Book book) {
Shelf shelf = new Shelf();
if (book.getAuthorId() != null) {
Author author = repository.findById(book.getAuthorId());
if (author != null && author.getName() != null) {
shelf.addAuthorName(author.getName());
}
}
return shelf;
}

This version seems much easier to read. I pay a lot of attention to the readability of the code that I write. And since I might be coming back to this code in a couple month time — I want to help my future-self and reduce the time that is needed to get an idea of what this code is doing. Also your teammates will thank you for writing easy-to-read code.

这个版本似乎更容易阅读。 我非常注意所编写代码的可读性。 而且由于我可能会在几个月后重新使用此代码,所以我想帮助我自己的未来,并减少了解此代码的工作所需的时间。 您的队友也将感谢您编写易于阅读的代码。

Having this in mind — I would be against using Optional in the example above as they make code hard to grasp at a glance. Using Optionals in your internal module which doesn’t expose any contacts to the outside world seems very much like overkill. Overkill in the sense that the price that is paid for reading and maintaining such code is much higher than the benefits.

考虑到这一点,我不赞成在上面的示例中使用Optional,因为它们会使代码一目了然。 在内部模块中使用Optionals不会将任何联系暴露给外界,这似乎非常过分。 从某种意义上讲,矫kill过正,即阅读和维护此类代码所付出的代价远高于收益。

好的用例 (Good use-case)

Use Optionals when you define contact of your library or your layer. Preferably if this library/layer is referenced in many other places. Ideal example would be — your repositories. Return Optional<T> from every method which returns a single object instead of just returning T:

在定义库或图层的接触时使用“可选”。 最好是在许多其他地方引用此库/层。 理想的例子是-您的存储库。 从每个返回单个对象而不是仅返回T的方法中返回Optional <T>

public Optional<Author> findById(long id) {
return findBy(...); // retrieve the author from the database
}

结论 (Conclusion)

Optionals are baked in into Java. This eases the adoption of this feature. However I encourage you to always apply a fair judgement when you want to use a particular feature of the language.

可选内容嵌入到Java中。 这简化了此功能的采用。 但是,我鼓励您在要使用语言的特定功能时始终做出公正的判断。

翻译自: https://medium.com/swlh/when-not-to-use-optionals-in-java-ddefe77c97c8

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值