http://dolszewski.com/java/java-default-parameters/

简短的回答:否。

幸运的是,您可以模拟它们。

许多编程语言(例如C ++或现代JavaScript)都有一个简单的选项来调用函数,而无需为其参数提供值。与其他语言相比,在Java中,默认方法参数需要更多的键入才能实现此效果。从本文中,您将学习Java中默认方法参数的工作方式

1.实践中的Java默认参数

Java语言的语法不允许您使用参数的预定义值声明方法。幸运的是,您可以通过简单的代码构造实现相同的效果。

您可以使用几个选项来模拟其他编程语言中已知的行为。您可以:

  • 使用方法重载
  • 允许空值作为输入
  • 用Java Varargs声明一个方法

让我们仔细看看这些选项。

1.1。具有方法重载的Java默认参数

在Java中实现默认方法参数的最佳选择可能是使用方法重载。方法重载使您可以使用相同名称但使用不同数量的参数来声明多个方法。

如何使用方法重载来模拟默认方法参数?

通过更简单的方法调用更复杂的方法。

这是一种方法的实际示例,该方法使您可以查询一些可选文档数:

  1. List search(String query) {`` ``return` `search(query, ``10``, ``0``);``}` `List search(String query, Integer limit, Integer offset) {`` ``// method implementation``}

唯一必需的参数是查询字符串。如您所见,您只需要使用最多参数即可实现该方法。为了阐明,简单方法只是将其参数传递给更复杂方法并为可选参数提供默认参数值的代理

与其他选项相比,方法重载的主要优点是客户端代码的简单性。您可以轻松读取给定方法允许使用哪些参数集。

尽管强烈建议方法重载,但是值得了解其他可能性。

1.2。允许将Null作为方法参数

另一种选择是声明一个接受所有可能参数的方法。接下来,在方法的主体中,您可以检查哪些参数为空值并为其指定默认值。

使用这种方法,我们前面的示例如下所示:

  1. List search(String query, Integer limit, Integer offset) {`` ``if` `(limit == ``null``) {`` ``limit = ``10``;`` ``}`` ``if` `(offset == ``null``) {`` ``offset = ``0``;`` ``}`` ``// method implementation``}

这种方法有两个主要缺点。首先,您仍然需要在客户端代码中传递所有参数。即使其中一些为空。其次,您需要知道哪些参数是可为空的,因为仅通过查看方法声明就无法分辨出来。

而且,许多开发人员认为重新确定方法参数是一种不好的做法,因为它会使代码难以遵循。考虑到这一点,许多静态代码分析工具都允许您检查这种代码的味道。

有人建议包装Java 8 Optional类中不需要的参数。但是,Optional类型设计用于方法输出而不是输入。如果您对为什么感兴趣,请参阅我的其他有关Java Optional用例的文章。

1.3。Varargs参数

Varargs选项仅限于相同类型和含义的参数。因此,它实际上并不能解决Java方法中默认参数的问题。但是您可能会在某些情况下考虑。

  1. User createUser(String login, Right... rights) {`` ``rights = User.DEFAULT_RIGHTS; `` ``// implementation``}

从技术上讲,甚至可以将Varargs用作单个可选参数。在这种情况下,您不必在客户端代码中传递null即可使用默认值。但是,它感觉像是一个可怕的骇客。我建议坚持方法重载。

2.长参数列表中的Java默认参数

当方法接受多个参数时,方法重载作为默认参数值的解决方案的主要问题就暴露出来了。为每种可能的参数组合创建重载方法可能很麻烦。

要解决此问题,您应该引入Parameter Object pattern

它是什么?

简而言之,参数对象是方法所有参数的包装对象

可是等等!我们不是只是将长参数列表的问题从方法转移到新类的构造函数上吗?

不死族,我们是。但是类构造函数为我们提供了另一种解决方案,即Builder模式。

2.1。使用参数对象解决Java默认参数

如前所述,您需要做的第一件事是包装方法参数列表的参数对象类。让我们看看上一个示例中的方法的外观:

  1. class` `SearchParams {` ` ``private` `static` `final` `int` `DEFAULT_LIMIT = ``10``;`` ``private` `static` `final` `int` `DEFAULT_OFFSET= ``0``;` ` ``private` `String query;`` ``private` `int` `limit = SearchParams.DEFAULT_LIMIT;`` ``private` `int` `offset = SearchParams.DEFAULT_OFFSET;` ` ``// getters` ` ``}` `}

如您所见,已实现的参数对象不过是普通的POJO。与常规方法参数列表相比,参数对象的优点在于,类字段可以具有默认值。就像上面的例子一样。

而已。现在,所有默认参数都放在一个位置。

2.2。…和建造者模式

为方法参数列表创建包装器类后,还应该创建一个对应的构建器类。通常,您将其作为内部静态类进行操作。

但是,不要单独键入构建器,而是要自动完成这项工作!

流行的Java IDE提供了生成生成器类的插件。

在我们的示例中,构建器将如下所示:

  1. class` `SearchParams {` ` ``// getters ...` ` ``private` `SearchParams(Builder builder) {`` ``query = builder.query;`` ``limit = builder.limit;`` ``offset = builder.offset;`` ``}` ` ``public` `static` `Builder newBuilder() {`` ``return` `new` `Builder();`` ``}` ` ``public` `static` `final` `class` `Builder {` ` ``private` `String query;`` ``private` `int` `limit;`` ``private` `int` `offset;` ` ``private` `Builder() {`` ``}` ` ``public` `Builder withQuery(String val) {`` ``query = val;`` ``return` `this``;`` ``}` ` ``public` `Builder withLimit(``int` `val) {`` ``limit = val;`` ``return` `this``;`` ``}` ` ``public` `Builder withOffset(``int` `val) {`` ``offset = val;`` ``return` `this``;`` ``}` ` ``public` `SearchParams build() {`` ``return` `new` `SearchParams(``this``);`` ``}` ` ``}` `}

最后一步是使用构建器来构造新的参数对象。在这种情况下,仅分配所选参数。对于您跳过的那些参数,将使用它们的默认值。这是一个例子:

  1. SearchParams params = SearchParams.newBuilder()`` ``.withQuery(``"gold"``)`` ``.withOffset(``20``)`` ``.build();``// params.limit = 10 by default

我们的示例非常简单,因为该方法只有三个参数,因此看起来像过度设计。实际上,当方法参数列表更长时,使用Parameter Object和Builder创建默认参数的解决方案大放异彩。

Java是否具有默认参数? - 图1

结论

让我们总结一下。

Java没有默认方法参数的简单解决方案,就像其他常见编程语言中提供的那样。但是,您可以使用其他Java结构和模式对其进行仿真。此外,您还将学习一种方法重载的简单方法,该方法适用于参数列表较短的方法。对于复杂的方法,“参数对象”模式更为灵活。

如果您发现该文章有用,请与您的朋友分享。不要忘记订阅,这样我就可以通知您其他类似的帖子。