2

我对 Java 以及 Python 和 PHP 还是很陌生,我习惯于函数参数的默认值。

所以我有编写方法的习惯,这些方法旨在从您只想设置一些值的稍微不同的情况下调用。例如,在我的 PHP 代码中,这很常见,因为我有工厂方法为对象实例提供稍微不同的属性。

在 Java 中,似乎我必须有一个需要所有参数的方法,然后是几个重载的变体,这些变体将调用该方法,其中一些参数设置为默认值,一些参数由调用者提供。这是,好吧,但有时会让我紧张。

我记得在我对 C++ 和 ActionScript 的一些简短考察中,这已经让我很恼火。现在,更有经验的 Java 开发人员是否有一些捷径?

在我看来,从技术上讲,这个问题已经被所有帖子的总和回答为“是的,它是”。我在下面打开了一个 wiki 帖子来收集各种替代解决方案,如果您愿意,请提供。我发现所有这些都非常有用,可以作为典型 Java 结构的灵感和学习示例。

4

7 回答 7

7

另一种选择是构建器模式的变体——你有一个代表所有参数的类型,构造该类型的实例(相应地默认),设置你想要的属性,然后将结果传递给原始方法,或者添加“参数类型”中的方法为您调用该方法。

ProcessBuilder您可以在标准库中通过和Process类看到这一点。

于 2009-03-06T10:02:08.370 回答
3

见可变参数

http://www.java-tips.org/java-se-tips/java.lang/using-the-varargs-language-feature.html

(更新的 URL;添加此评论是因为 stackoverflow 需要 >30 个字符)

于 2009-03-06T09:59:01.530 回答
2

为了使这更简单,我为默认值创建了一个注释,并创建了一个注释处理器,该处理器生成一个具有重载方法的超类。例如:

protected void process(
    Processor processor,
    String item,
    @Default("Processor.Size.LARGE") Size size,
    @Default("red") String color,
    @Default("1") int quantity) {
        ...
}

生成(在生成的超类中)

protected void process(sample.Processor processor, java.lang.String item)  {
    process(processor, item, Processor.Size.LARGE, "red", 1);
}
protected void process(sample.Processor processor, 
                       java.lang.String item, 
                       sample.Processor.Size size)  {
    process(processor, item, size, "red", 1);
}
protected void process(sample.Processor processor, 
                       java.lang.String item, 
                       sample.Processor.Size size, 
                       java.lang.String color)  {
    process(processor, item, size, color, 1);
}
protected abstract void process(sample.Processor processor, 
                                java.lang.String item, 
                                sample.Processor.Size size, 
                                java.lang.String color, 
                                int quantity) ;

请参阅http://code.google.com/p/javadude/wiki/Annotations -- Scott

于 2009-03-06T18:35:32.427 回答
1

尝试将您的思考过程从一种语言翻译成另一种语言可能非常困难。正如其他人所指出的那样,您可以做一些工作来获得您想要的东西......但是您越早“接受”Java 设计的工作方式,您在使用 Java 时就会做得更好。

我不得不做一些 PHP 的东西......让我很恼火,因为我无法让它做我想做的事......所以它是双向的。

您将遇到的最大障碍可能是静态类型。您可以尝试做一些事情来解决它,但最终它们将是一个非常大的黑客。

在 C++ 的早期,人们试图说服 C++ 表现得像 Smalltalk……但效果不佳。在早期,如果 Java 人试图获取他们的 C++ 知识并在 Java 中使用它......并没有很好地工作(这令人倍感沮丧,因为这些语言在表面上非常相似)。

我的建议是,对于您的 Java 编码,学习像 Java 开发人员而不是 PHP 开发人员一样编程。

对于您的直接问题,您是否真的应该从工厂重新调整不同的类,而不是创建具有不同变量集的相同类型的对象?

于 2009-03-06T10:39:37.983 回答
0

只要您以 OO 方式编码,您就不会错过 Java 中的默认值。默认参数仅在过程编码风格中很方便。

在 OO 中,不是通过方法/过程传递状态,而是状态已经在您调用的对象中,或者您作为参数传递的对象中。大多数时候,您的方法中需要的参数不超过 1 或 2 个。

如果你想在使用它之前配置你的对象,你可以用一个简单的构造函数来构造它,然后调用不同的 setter。与调用具有许多参数的构造函数相比,这使代码更具可读性(因为您看到了 setter 名称)。如果稍后出现新属性,您可以将其添加到对象中,而无需修改现有的工厂方法。

于 2009-03-06T10:19:40.263 回答
0

看起来,“是的,它是”,除了:

类似的效果可以通过 Paul Whelan 建议的varargs或通过定义一个额外的类型来实现,该类型携带参数作为具有正确默认值的字段,如 Jon Skeet 建议的那样。Boris Pavlović 补充说,他的类型可以是一个内部静态类,以将事物整齐地放在正确的位置。

缺点(请注意,这整个问题不是关于任何严重的影响,只是关于方便的调整):

Varargs 似乎最适合传递具有非常相似的形式和大部分等效含义的可变长度值列表,例如名称列表。如果用于问题中所述的目的,则该方法必须对列表执行各种检查才能对其进行解释,这似乎不多,但不太方便。

如果结果类型可以用于其他用途,而不仅仅是传递给一个特定方法,或者当它是一组更复杂的参数时,携带参数的特殊类型似乎最有用。如果有 2-4 个参数,有些可能有默认值,重载似乎仍然更方便一些,但这可能是个人喜好问题。

于 2009-03-06T10:25:26.677 回答
0

是的,oop 的重载是在 java 中使用 Default 参数的唯一方法。但这是给你的黑客。如果您使用重载并且想要使用默认参数。然后你会结束

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) { }

但是通过使用可变参数

public class DefaultValue
{
 public static void main(String[] args)
  {
       defaultParameter();
       defaultParameter(true);
  }

  public static void defaultParameter(Boolean …gender)
  {
       boolean genderBoolean = false; // It is the default value you want to give
       if(1 == gender.length)
       {
            genderBoolean = gender[0]; // Overrided Value
      }
       System.out.println(genderBoolean);
 }
}

上面的代码输出将是

false
true

有关更多类似示例和说明,请访问java-default-parameter-values

于 2016-08-20T03:37:24.523 回答