java - Java是否支持默认参数的值?

  显示原文与译文双语对照的内容

我遇到了一些具有以下结构的Java代码:


public MyParameterizedFunction(String param1, int param2)
{
 this(param1, param2, false);
}

public MyParameterizedFunction(String param1, int param2, boolean param3)
{
//use all three parameters here
}

我知道在 C++ 中我可以给一个参数赋值。 例如:


void MyParameterizedFunction(String param1, int param2, bool param3=false);

Java支持这种语法? 这两个步骤的语法是可取的有什么原因?

时间:

不,你发现的结构是Java如何处理它的( 也就是说,重载而不是默认参数) 。

对于构造函数, 。会看到 Effective Java: 编程语言的指南 1 项尖端( 考虑静态工厂方法而不是构造函数) 如果重载得到复杂。 对于其他方法,重命名某些事例或者使用参数对象可以帮助。 这就是你有足够的复杂性,区别是困难的。 明确的情况是你必须使用参数的顺序来区分,而不仅仅是数字和类型。

否,但你可以使用生成器模式,如中所述,这个堆栈溢出答案。

就像链接的回答中所述,生成器模式允许你编写代码,比如


Student s1 = new StudentBuilder().name("Eli").buildStudent();
Student s2 = new StudentBuilder()
. name("Spicoli")
. age(16)
. motto("Aloha, Mr Hand")
. buildStudent();

其中一些字段可以有默认值,或者是可选的。

,没有。

在Java中模拟默认参数有几种方法:

  1. 方法重载。

    
    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");
    
    

    这种方法的一个局限性是,如果有两个相同类型的可选参数,并且它们中的任何一个都可以省略,则它不起作用。

  2. 可变参数。

    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);
    
    

    可选参数类型可能不同:

    
    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");
    
    

    这里方法的主要缺点是,如果可选参数的类型不同,则会丢失静态类型检查。 而且,如果每个参数都有不同的含义,你需要一些方法来区分它们。

  3. 在方法中 body, 像以往的制约让你可以允许空值 null 。 以地址进行有效的分析和每个 parameter:

    
    void foo(String a, Integer b, Integer c) {
     b = b!= null? b : 0;
     c = c!= null? c : 0;
    //...
    }
    
    foo("a", null, 2);
    
    

    现在必须提供所有参数值,但默认的值可能为空。

  4. 于有一个默认的参数相关 value, 可选的类。 该方法类似于在null值,只需要使用 Guava 可选 class:

    
    void foo(String a, Optional<Integer> bOpt) {
     Integer b = bOpt.isPresent()? bOpt.get() : 0;
    //...
    }
    
    foo("a", Optional.of(2));
    foo("a", Optional.<Integer>absent());
    
    

    可选为调用方指定了方法约定,但是,可能会发现该签名太冗长。

  5. 生成器模式。 生成器模式用于构造函数并通过引入单独的生成器类实现:

    
     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();
    
    
  6. 地图。 当参数的数量太大并且为大部分用户默认值通常被用来作为他们的名字/值:的地图,你可以传递方法参数

    
    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 = (String)parameters.get("a");
     }
     if (parameters.containsKey("b")) { 
    //... 
     }
    //...
    }
    
    foo(ImmutableMap.<String, Object>of(
    "a","a",
    "b", 2, 
    "d","value")); 
    
    

请注意,你可以结合这些方法中的任何一个来达到一个理想的结果。

不幸的是,是的。


void MyParameterizedFunction(String param1, int param2, bool param3=false) {}

可以用 Java 1.5写成:


void MyParameterizedFunction(String param1, int param2, Boolean... params) {
 assert params.length <= 1;
 bool param3 = params.length> 0? params[0].booleanValue() : false;
}

但是你是否应该依赖你对编译器生成一个

 
new Boolean[]{}

 

对于每个调用。

对于多个defaultable参数:


void MyParameterizedFunction(String param1, int param2, bool param3=false, int param4=42) {}

可以用 Java 1.5写成:


void MyParameterizedFunction(String param1, int param2, Object... p) {
 int l = p.length;
 assert l <= 2;
 assert l <1 || Boolean.class.isInstance(p[0]);
 assert l <2 || Integer.class.isInstance(p[1]);
 bool param3 = l> 0 && p[0]!= null? ((Boolean)p[0]).booleanValue() : false;
 int param4 = l> 1 && p[1]!= null? ((Integer)p[1]).intValue() : 42;
}

这符合 C++ 语法,它只允许在参数列表末尾使用默认参数。

除了语法之外,对于传递的defaultable参数,还有一个不同的运行时类型检查,在编译过程中 C++ 类型检查它们。

你可以在 Scala 中执行,它在JVM上运行,并且与Java程序兼容。 http://www.scala-lang.org/

等等


class Foo(var prime: Boolean = false, val rib: String) {}

我可能在这里声明了显而易见的一点,但为什么不简单地实现"默认"参数?


public class Foo() {
 public void func(String s){
 func(s, true);
 }
 public void func(String s, boolean b){
//your code here
 }
}

默认情况下,你将使用乙醚

func("my string") ;

如果你不想使用默认值,你将使用

func("my string", false) ;

不,一般Java没有太多的( 任意) 语法糖,因为他们试图制作一个简单的语言。

不支持它,但有几个选项,比如使用参数对象模式和一些语法糖:


public class Foo() {
 private static class ParameterObject {
 int param1 = 1;
 String param2 ="";
 }

 public static void main(String[] args) {
 new Foo().myMethod(new ParameterObject() {{ param1 = 10; param2 ="bar";}});
 }

 private void myMethod(ParameterObject po) {
 }
}

在这个示例中,我们用默认值构造 ParameterObject,并在类实例初始化节中重写它们 { param1 = 10; param2 ="bar";}

有半打或者更高的问题,这样的问题,最终你到达静态工厂模式。 请查看加密 api 。 很难解释,但要这样思考: 如果你有一个构造函数,默认或者其他方法,在大括号之外传播状态的唯一方法是拥有一个布尔值 isValid ;( 连同默认值为默认值v 失败的构造函数) 或者抛出从字段用户返回的异常。

代码正确,我写了上千行构造函数,然后做我需要的。 我发现在对象构造处使用 isValid - 换句话说,两个行构造函数- 但是由于某些原因我迁移到静态工厂模式。 我只是觉得如果你在一个方法调用中可以做很多事情,仍然有 sync() 问题,但是默认情况下是'已经替换'( 更安全)

我认为我们需要做的是将null作为默认值vis-a-vis的问题作为成员变量 one=new String("");,然后在赋值给构造函数之前检查 null 。

在Java中完成的原始的平流层计算机科学数量非常惊人。

C++ 等有供应商库,是的。 在大规模的服务器上,Java可以胜过他们,因为它是大规模的工具箱。 研究静态初始值设定块,与我们保持一致。

...