Java 可选参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/965690/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java optional parameters
提问by Mike Pone
How do I use optional parameters in Java? What specification supports optional parameters?
如何在 Java 中使用可选参数?什么规范支持可选参数?
采纳答案by laginimaineb
varargs could do that (in a way). Other than that, all variables in the declaration of the method must be supplied. If you want a variable to be optional, you can overload the method using a signature which doesn't require the parameter.
varargs 可以做到这一点(在某种程度上)。除此之外,必须提供方法声明中的所有变量。如果您希望变量是可选的,您可以使用不需要参数的签名来重载该方法。
private boolean defaultOptionalFlagValue = true;
public void doSomething(boolean optionalFlag) {
...
}
public void doSomething() {
doSomething(defaultOptionalFlagValue);
}
回答by Dario
There are no optional parameters in Java. What you can do is overloading the functions and then passing default values.
Java 中没有可选参数。您可以做的是重载函数,然后传递默认值。
void SomeMethod(int age, String name) {
//
}
// Overload
void SomeMethod(int age) {
SomeMethod(age, "John Doe");
}
回答by Scott Stanchfield
Unfortunately Java doesn't support default parameters directly.
不幸的是,Java 不直接支持默认参数。
However, I've written a set of JavaBean annotations, and one of them support default parameters like the following:
但是,我编写了一组 JavaBean 注释,其中一个支持如下默认参数:
protected void process(
Processor processor,
String item,
@Default("Processor.Size.LARGE") Size size,
@Default("red") String color,
@Default("1") int quantity) {
processor.process(item, size, color, quantity);
}
public void report(@Default("Hello") String message) {
System.out.println("Message: " + message);
}
The annotation processor generates the method overloads to properly support this.
注释处理器生成方法重载以正确支持这一点。
See http://code.google.com/p/javadude/wiki/Annotations
请参阅http://code.google.com/p/javadude/wiki/Annotations
Full example at http://code.google.com/p/javadude/wiki/AnnotationsDefaultParametersExample
http://code.google.com/p/javadude/wiki/AnnotationsDefaultParametersExample 上的完整示例
回答by Yishai
VarArgs and overloading have been mentioned. Another option is a Builder pattern, which would look something like this:
已经提到了 VarArgs 和重载。另一种选择是 Builder 模式,它看起来像这样:
MyObject my = new MyObjectBuilder().setParam1(value)
.setParam3(otherValue)
.setParam6(thirdValue)
.build();
Although that pattern would be most appropriate for when you need optional parameters in a constructor.
尽管该模式最适合在构造函数中需要可选参数的情况。
回答by bhoot
There is optional parameters with Java 5.0. Just declare your function like this:
Java 5.0 有可选参数。只需像这样声明你的函数:
public void doSomething(boolean... optionalFlag) {
//default to "false"
//boolean flag = (optionalFlag.length >= 1) ? optionalFlag[0] : false;
}
you could call with doSomething();
or doSomething(true);
now.
你可以打电话给doSomething();
或doSomething(true);
现在。
回答by theninjagreg
You can use something like this:
你可以使用这样的东西:
public void addError(String path, String key, Object... params) {
}
The params
variable is optional. It is treated as a nullable array of Objects.
该params
变量是可选的。它被视为一个可为空的对象数组。
Strangely, I couldn't find anything about this in the documentation, but it works!
奇怪的是,我在文档中找不到任何关于此的信息,但它有效!
This is "new" in Java 1.5 and beyond (not supported in Java 1.4 or earlier).
这是 Java 1.5 及更高版本中的“新”功能(Java 1.4 或更早版本不支持)。
I see user bhoot mentioned this too below.
我看到用户 bhoot 在下面也提到了这一点。
回答by az3
In JDK>1.5 you can use it like this;
在JDK>1.5中可以这样使用;
public class NewClass1 {
public static void main(String[] args) {
try {
someMethod(18); // Age : 18
someMethod(18, "John Doe"); // Age & Name : 18 & John Doe
} catch (Exception e) {
e.printStackTrace();
}
}
static void someMethod(int age, String... names) {
if (names.length > 0) {
if (names[0] != null) {
System.out.println("Age & Name : " + age + " & " + names[0]);
}
} else {
System.out.println("Age : " + age);
}
}
}
回答by Vitalii Fedorenko
There are several ways to simulate optional parameters in Java:
Java中有几种模拟可选参数的方法:
Method overloading.
void foo(String a, Integer b) { //... } void foo(String a) { foo(a, 0); // here, 0 is a default value for b } foo("a", 2); foo("a");
One of the limitations of this approach is that it doesn't work if you have two optional parameters of the same type and any of them can be omitted.
Varargs.
a) All optional parameters are of the same type:
void foo(String a, Integer... b) { Integer b1 = b.length > 0 ? b[0] : 0; Integer b2 = b.length > 1 ? b[1] : 0; //... } foo("a"); foo("a", 1, 2);
b) Types of optional parameters may be different:
void foo(String a, Object... b) { Integer b1 = 0; String b2 = ""; if (b.length > 0) { if (!(b[0] instanceof Integer)) { throw new IllegalArgumentException("..."); } b1 = (Integer)b[0]; } if (b.length > 1) { if (!(b[1] instanceof String)) { throw new IllegalArgumentException("..."); } b2 = (String)b[1]; //... } //... } foo("a"); foo("a", 1); foo("a", 1, "b2");
The main drawback of this approach is that if optional parameters are of different types you lose static type checking. Furthermore, if each parameter has the different meaning you need some way to distinguish them.
Nulls.To address the limitations of the previous approaches you can allow null values and then analyze each parameter in a method body:
void foo(String a, Integer b, Integer c) { b = b != null ? b : 0; c = c != null ? c : 0; //... } foo("a", null, 2);
Now all arguments values must be provided, but the default ones may be null.
Optional class.This approach is similar to nulls, but uses Java 8 Optional class for parameters that have a default value:
void foo(String a, Optional<Integer> bOpt) { Integer b = bOpt.isPresent() ? bOpt.get() : 0; //... } foo("a", Optional.of(2)); foo("a", Optional.<Integer>absent());
Optional makes a method contract explicit for a caller, however, one may find such signature too verbose.
Update: Java 8 includes the class
java.util.Optional
out-of-the-box, so there is no need to use guava for this particular reason in Java 8. The method name is a bit different though.Builder pattern.The builder pattern is used for constructors and is implemented by introducing a separate Builder class:
class Foo { private final String a; private final Integer b; Foo(String a, Integer b) { this.a = a; this.b = b; } //... } class FooBuilder { private String a = ""; private Integer b = 0; FooBuilder setA(String a) { this.a = a; return this; } FooBuilder setB(Integer b) { this.b = b; return this; } Foo build() { return new Foo(a, b); } } Foo foo = new FooBuilder().setA("a").build();
Maps.When the number of parameters is too large and for most of the default values are usually used, you can pass method arguments as a map of their names/values:
void foo(Map<String, Object> parameters) { String a = ""; Integer b = 0; if (parameters.containsKey("a")) { if (!(parameters.get("a") instanceof Integer)) { throw new IllegalArgumentException("..."); } a = (Integer)parameters.get("a"); } if (parameters.containsKey("b")) { //... } //... } foo(ImmutableMap.<String, Object>of( "a", "a", "b", 2, "d", "value"));
In Java 9, this approach became easier:
@SuppressWarnings("unchecked") static <T> T getParm(Map<String, Object> map, String key, T defaultValue) { return (map.containsKey(key)) ? (T) map.get(key) : defaultValue; } void foo(Map<String, Object> parameters) { String a = getParm(parameters, "a", ""); int b = getParm(parameters, "b", 0); // d = ... } foo(Map.of("a","a", "b",2, "d","value"));
方法重载。
void foo(String a, Integer b) { //... } void foo(String a) { foo(a, 0); // here, 0 is a default value for b } foo("a", 2); foo("a");
这种方法的一个限制是,如果您有两个相同类型的可选参数并且其中任何一个都可以省略,则它不起作用。
可变参数。
a) 所有可选参数的类型相同:
void foo(String a, Integer... b) { Integer b1 = b.length > 0 ? b[0] : 0; Integer b2 = b.length > 1 ? b[1] : 0; //... } foo("a"); foo("a", 1, 2);
b) 可选参数的类型可能不同:
void foo(String a, Object... b) { Integer b1 = 0; String b2 = ""; if (b.length > 0) { if (!(b[0] instanceof Integer)) { throw new IllegalArgumentException("..."); } b1 = (Integer)b[0]; } if (b.length > 1) { if (!(b[1] instanceof String)) { throw new IllegalArgumentException("..."); } b2 = (String)b[1]; //... } //... } foo("a"); foo("a", 1); foo("a", 1, "b2");
这种方法的主要缺点是,如果可选参数的类型不同,则会丢失静态类型检查。此外,如果每个参数具有不同的含义,您需要某种方式来区分它们。
空值。为了解决之前方法的局限性,您可以允许空值,然后分析方法主体中的每个参数:
void foo(String a, Integer b, Integer c) { b = b != null ? b : 0; c = c != null ? c : 0; //... } foo("a", null, 2);
现在必须提供所有参数值,但默认值可能为空。
选修课。这种方法类似于空值,但对具有默认值的参数使用 Java 8 Optional 类:
void foo(String a, Optional<Integer> bOpt) { Integer b = bOpt.isPresent() ? bOpt.get() : 0; //... } foo("a", Optional.of(2)); foo("a", Optional.<Integer>absent());
Optional 使调用者的方法契约显式化,但是,人们可能会发现这样的签名过于冗长。
更新:Java 8 包含
java.util.Optional
开箱即用的类,因此在 Java 8 中没有必要出于这个特殊原因使用 guava。不过方法名称有点不同。建造者模式。构建器模式用于构造器,通过引入一个单独的 Builder 类来实现:
class Foo { private final String a; private final Integer b; Foo(String a, Integer b) { this.a = a; this.b = b; } //... } class FooBuilder { private String a = ""; private Integer b = 0; FooBuilder setA(String a) { this.a = a; return this; } FooBuilder setB(Integer b) { this.b = b; return this; } Foo build() { return new Foo(a, b); } } Foo foo = new FooBuilder().setA("a").build();
地图。当参数数量太大并且通常使用大多数默认值时,您可以将方法参数作为其名称/值的映射传递:
void foo(Map<String, Object> parameters) { String a = ""; Integer b = 0; if (parameters.containsKey("a")) { if (!(parameters.get("a") instanceof Integer)) { throw new IllegalArgumentException("..."); } a = (Integer)parameters.get("a"); } if (parameters.containsKey("b")) { //... } //... } foo(ImmutableMap.<String, Object>of( "a", "a", "b", 2, "d", "value"));
在 Java 9 中,这种方法变得更容易:
@SuppressWarnings("unchecked") static <T> T getParm(Map<String, Object> map, String key, T defaultValue) { return (map.containsKey(key)) ? (T) map.get(key) : defaultValue; } void foo(Map<String, Object> parameters) { String a = getParm(parameters, "a", ""); int b = getParm(parameters, "b", 0); // d = ... } foo(Map.of("a","a", "b",2, "d","value"));
Please note that you can combine any of these approaches to achieve a desirable result.
请注意,您可以结合使用这些方法中的任何一种来获得理想的结果。
回答by Parvinder Singh
Default arguments can not be used in Java. Where in C#, C++ and Python, we can use them..
Java 中不能使用默认参数。在 C#、C++ 和 Python 中,我们可以使用它们。
In Java, we must have to use 2 methods (functions) instead of one with default parameters.
在 Java 中,我们必须使用 2 种方法(函数)而不是一种带有默认参数的方法。
Example:
例子:
Stash(int size);
Stash(int size, int initQuantity);
回答by Jigar Shah
Overloading is fine, but if there's a lot of variables that needs default value, you will end up with :
重载很好,但如果有很多变量需要默认值,你最终会得到:
public void methodA(A arg1) { }
public void methodA( B arg2,) { }
public void methodA(C arg3) { }
public void methodA(A arg1, B arg2) { }
public void methodA(A arg1, C arg3) { }
public void methodA( B arg2, C arg3) { }
public void methodA(A arg1, B arg2, C arg3) { }
So I would suggest use the Variable Argument provided by Java. Here's a linkfor explanation.
所以我建议使用 Java 提供的变量参数。这是一个解释的链接。