HOWTO · Java

Java 默认参数

本文介绍 Java 是否支持默认参数。

本页内容

Java 的方法声明不支持默认参数值。每次调用都必须为所有必需的固定参数提供实参;varargs 参数则可以接收零个或多个实参。省略固定参数时,编译器不会自动补入值。若要提供可选行为,可以定义重载方法、通过 varargs 接受数量可变的同类型值,或在 API 中明确表示缺失状态。这些方式解决的问题各不相同:请根据调用方需要的是少数固定选项、长度可变的列表,还是区分“未提供”和已提供值的能力来选择。

Java 是否支持默认参数值?

不支持。Java 方法签名会声明每次调用都必须传入的参数。例如,声明为 send(String recipient, String subject) 的方法不能只传入收件人来调用。Java 不会根据声明推断主题,也不会自动应用默认值。方法体可以在收到参数后选择一个备用值,但这是应用逻辑,不是语言层面的默认参数。

参数选项较少时使用方法重载

方法重载能为调用方提供几种明确的调用形式。参数较少的重载方法可以将备用值传给完整方法。当常见选项不多时,这种方式很实用,而且备用值在代码中一目了然。下面的示例中,调用只接收一个参数的重载方法时,问候语会使用 "Hello" 作为默认值。

运行此示例:

本节中的代码以及显示的标签或输出仍为英文。

public class GreetingExample {
    static String greet(String name) {
        return greet(name, "Hello");
    }

    static String greet(String name, String greeting) {
        return greeting + ", " + name + "!";
    }

    public static void main(String[] args) {
        System.out.println(greet("Maya"));
        System.out.println(greet("Maya", "Welcome"));
    }
}
Hello, Maya!
Welcome, Maya!

重载方法会明确传入备用值;编译器不会替你传入。可选参数增多时,重载会变得繁琐。如果两个可选参数类型相同,而且调用方可以分别省略其中任意一个,方法签名中的参数类型就无法表明省略的是哪一个。要支持许多组合,可能需要编写许多不同的方法签名。若调用方需要多种组合,可以改用名称清晰的方法或选项对象。

参数数量可变且类型相同时使用 varargs

varargs 参数写作 Type... values,让方法能够接收零个或多个该类型的实参。在方法内部,Java 会将这些实参作为数组提供。实参数量确实会变化时,varargs 很有用;它不会为省略的固定参数定义备用值。方法可以自行决定零个实参代表什么,例如本例在列表为空时返回零。

本节中的代码以及显示的标签或输出仍为英文。

public class SumExample {
    static int sum(int... values) {
        int total = 0;
        for (int value : values) {
            total += value;
        }
        return total;
    }

    public static void main(String[] args) {
        System.out.println(sum());
        System.out.println(sum(4, 7, 9));
    }
}
0
20

没有实参时返回零,是该方法自行选择的求和规则,并不是 Java 自动提供的默认实参值。一个方法只能有一个 varargs 参数,而且它必须是最后一个参数,因此固定参数必须放在它前面。

省略参数与传入某个值含义不同时,使用哨兵值或包装类型

空字符串("")是真实的字符串值,只是其中没有字符。null 是另一种引用值,而省略的实参则根本没有传入。空文本和 null 都不会自动替代缺失的实参。如果空字符串就是所需的值,就使用它;只有当 API 明确定义了 null 的含义且调用方能够安全处理时,才使用 null。

如果调用方必须区分“未提供”和所有有效值,就应明确表示这种状态。对于可空引用,约定并记录 null 的含义可能已经足够,但它不能表示基本类型参数的缺失,也容易被误用。对于引用值,Optional<String> 这样的包装类型可以明确表示是否存在;有多个可选设置时,选项类或构建器通常更清晰。这些做法仍要求调用方传入包装类型或选项对象:它们是在 API 内表示缺失状态,并没有给 Java 增加原生默认参数。