写java代码时的注意事项
Java 8引入的Optional类一直是该语言版本引入的最具争议的功能之一。 尽管我喜欢这个新的Java类的东西比不喜欢的东西多,但在Java方法中将其用作return
类型时,需要考虑一些事情。 我将在本文中讨论其中的一些问题,但不要讨论是否应该将Optional
限制为返回类型的争论 。 我还假设仅在期望某些情况下该方法不应该返回任何值的情况下,才将Optional
用作返回类型。 最后,这些观察结果适用于其他类型,并且也直接在Java中直接使用null
,但是Optional
强调并具体说明了这些观察结果。
单一收益与多重收益
在一般的软件开发社区和Java开发社区中,有一段时间一直在争论(“ 宗教战争 ”)有关是否应该编写只return
一次的方法(在此讨论中不算抛出异常 )。 一方面, Yegor Bugayenko认为“ 许多返回语句在OOP中不是一个好主意 ”, Tom Dalling认为“ 从函数中获得一个退出点(返回)是一件好事 ”,而且许多人认为经常有多个return
语句表明需要重构该方法 。 在另一边, 布鲁斯·埃克尔认为多个return
语句可以使代码“更清晰”, 泰勒·戈蒂埃认为,“ 格言 ”,“一种方法,应该有一个且只有一个出口点”,“可能是十分错误的”, 彼得· Ritchie认为, 严格遵守单一出口可能会导致当今“面向对象的语言”中的“可读性较低”的代码, Mark Levison概述了“ 一些我不喜欢单一出口论点的原因 。”
Nicolai Parlog在“ 多个返回语句 ”一文中 ,介绍了方法仅返回一次的想法的历史以及需要考虑的事项。 他包括“多重收益表的情况”一节,其中概述了“一种方法可以从多个收益表中获利的几种情况。” 我最好的猜测是,许多开发商觉得我做的方式,这是“这取决于”决定一个特定的方法是否应该只有一个的时候return
陈述或应该有一个以上的return
声明。
当我开始更频繁地将Java 8的Optional用于我的方法的返回类型时,我发现在确定是从方法中返回一次还是多次时,还要考虑使用Optional作为返回类型。
在声明Java方法返回Optional
,重要的是要充分理解这并不妨碍编写此方法的开发人员返回null
。 返回的Optional
是引用类型,并且与任何引用类型一样,可以为null
。 至关重要的是,编写返回Optional
的方法的开发人员永远不要让该方法返回null
[通常应返回Optional.empty()代替]。 我将用两句话来重申这一点:
- 第三版 , 有效Java中项目#55中的突出显示句子:“ 切勿从
Optional
-returning方法返回空值。 “ - 斯图尔特·马克(Stuart Marks)使用
Optional
的#1规则 ,“永远,永远不要对Optional变量或返回值使用null。”
一个方法中针对多个return语句的参数之一是,它使得识别每种情况下返回的内容变得更加困难(查找所有可能的返回方案)。 使用Optional
作为返回类型的一个具体示例说明了这一点。 一个人要确保在某些情况下一个人的方法不会返回null
,在其他情况下要确保一个Optional
实例。 编译器当然不会在每种情况下返回哪个值。
处理此问题的一种方法是仅从方法返回一次,然后开发人员编写代码,而开发人员检查代码则可以轻松地确保不返回null
。 这些开发人员将只需要查找Optional.of(T)调用, Optional.ofNullable(T)调用或Optional.empty()调用。
在方法中使用基础数据类型的局部变量
当在返回点实例化Optional
时,这种避免意外返回null
而不是空Optional
最有效。 换句话说,我发现最好在整个方法中使用Optional
包装的类型,然后在最后可能的时候将其放在Optional
中。 下一个代码清单提供了一些可笑的琐碎示例。
声明最终以可选方式返回的局部变量的示例
/*** Provides the middle name if it exists.** @return Middle name if it exists or empty if it doesn't exist.*/
public Optional<String> determineMiddleName1()
{String middleName;// Do whatever logic is necessaryreturn Optional.ofNullable(middleName);
}/*** Provides the middle name if it exists.** @return Middle name if it exists or empty if it doesn't exist.*/
public Optional<String> determineMiddleName2()
{Optional<String> middleName;// Do whatever logic is necessaryreturn middleName;
}
在上面的代码中, determineMiddleName 1 ()
方法与基础类型的局部变量一起使用。 通常,这比Optional
更容易设置/填充,并且在末尾使用Optional.isNullable()
可确保即使null
中间名也将作为“空”的Optional
而不是null
。
上面的代码中的defineMiddleName determineMiddleName 2 ()
方法声明其局部变量,该局部变量最终将作为Optional<String>
返回,然后在该方法的末尾返回该引用。
避免局部变量的“默认”初始化
在上面编写方法defineMiddleName determineMiddleName 2 ()
,编译器将帮助确保将局部变量“ middleName”设置为某物(即使该“ something”为null
),但开发人员已选择将其“ middleName”变量初始化为开头为null
,则编译器将不会有任何问题。 如果由于某种原因需要初始化局部变量,最好将其初始化为Optional.empty()
而不是null
。 如果开发人员选择使用Optional.empty()
初始化该变量,那么第二个示例仍然有可能在该方法的后面将本地变量“重置”为null
。
该讨论使我对Java中将Optional
用作方法返回类型有三点看法。
- 单一
return
或多重return
对意外返回null
而不是“空”或其他非null
的可能性的影响在确定单一收益或多重收益是否最有意义时,应考虑Optional
引用。 - 通过在整个方法中处理基础类型并仅在最新时刻(通常在
return
)实例化返回的Optional
,通常更容易确保返回Optional
引用而不是返回null
。 - 最终将要从方法返回的
Optional
类型的局部变量,即使“已知”将适当地重新设置,也绝不应该最初将其分配为null
。 最好根本不要定义它,以便编译器将确保需要在代码流的每个“分支”中对其进行设置。 最起码,如果是进行初始化,类型的那个局部变量Optional
应该被初始化为Optional.empty()
而不是向null
。
这些观察可以合并。 例如,当确定某个方法应具有多个返回(例如实现guard子句 )时,可以在每次返回时返回适当的非null
Optional
引用,并且直到需要时才初始化局部变量(通过警卫)。 下一个可笑的例子说明了这一点。
避免使用多个返回语句返回空值的示例
public Optional<String> getGuardedData(final String input)
{if (input == null){return Optional.empty();}String data;// Do whatever logic is necessaryreturn Optional.ofNullable(data);
}
我发现Optional
类,当正确用作方法返回类型时,由于它的流利性更高,可以使客户端的代码更具可读性。 但是,要获得其最大值,必须遵循纪律应用Optional
,以便代码的客户可以期望返回的Optional
永远不会为null
。 这篇文章研究了一些注意事项,可以帮助确保从不会将自已声明为return Optional
的方法返回null
。 没有信任,该方法不会返回null
,使用Optional
的返回类型只能使事情变得更糟,因为它迫使客户端的非第一次检查null
Optional
调用上的方法之一,之前Optional
。 这使得调用代码不太流畅 。
翻译自: https://www.javacodegeeks.com/2018/01/considerations-returning-java-8s-optional-method.html
写java代码时的注意事项