我是Java的新手,从Python和PHP开始,我习惯了函数参数的默认值。
所以我养成了编写方法的习惯,这些方法旨在从稍微不同的情况调用,你只想设置一些值。例如,在我的PHP代码中,这种情况很常见,因为我有工厂方法为对象实例提供稍微不同的属性。
在Java中,似乎我必须有一个方法需要所有参数,然后是几个重载的变量,这些变量将调用该方法,其中一些参数设置为默认值,一些参数由调用者提供。哪,好吧,好吧,但有时会让我紧张。
我记得在一些短暂的C ++和ActionScript短途旅行中,这已经让我烦恼了。现在,更有经验的Java开发人员有这方面的一些捷径吗?
在我看来,从技术上讲,这个问题已被所有帖子的总和回答为“是的,它是”。我在下面打开了一个wiki帖子来收集各种替代解决方案,如果您愿意,请提供帮助。我发现所有这些都非常有用,可以作为典型Java构造的灵感和学习示例。
答案 0 :(得分:7)
另一个选项是构建器模式的变体 - 您有一个表示所有参数的类型,构造该类型的实例(相应地默认),设置所需的属性,然后将结果传递给原始方法,或在“参数类型”中添加一个方法来为您调用该方法。
您可以使用ProcessBuilder
和Process
类在标准库中查看此操作。
答案 1 :(得分:3)
见varargs
http://www.java-tips.org/java-se-tips/java.lang/using-the-varargs-language-feature.html
(更新的网址;此评论已添加,因为stackoverflow需要> 30个字符)
答案 2 :(得分: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) ;
答案 3 :(得分:1)
尝试将你的过程从一个语言转换为另一个语言可能非常困难。正如其他人所指出的那样,你可以做一些工作来获得你想要的东西......但是你越早“接受”Java的工作方式就越好,你将在Java工作时使用。
我不得不做一些PHP的东西......让我感到烦恼,我无法让它做我想做的事......所以它是双向的。
您遇到的最大障碍可能是静态打字。有些事情你可以尝试去解决它,但最终它们将是一个非常大的黑客。
在C ++的早期,人们试图说服C ++表现得像Smalltalk ......但效果不佳。在早期,如果Java人们试图获取他们的C ++知识并在Java中使用它...没有太好用(这是令人沮丧的,因为表面上的语言非常相似)。
我的建议是,您的Java编码学会像Java开发人员而不是PHP开发人员那样编程。
对于您当前的问题,是否可能真的要从工厂重新调整不同的类而不是创建具有不同变量的同类对象?
答案 4 :(得分:0)
只要您以OO方式编码,就不会错过Java中的默认值。默认参数仅在过程编码风格中很方便。
在OO中,而不是通过方法/过程传递状态,状态已经在您调用的对象中,或者您作为参数传递的对象。大多数情况下,您的方法中不需要超过1或2个参数。
如果要在使用之前配置对象,可以使用简单的构造函数构造它,然后调用不同的setter。与调用具有许多参数的构造函数相比,这使代码更具可读性(因为您看到了setter名称)。 如果以后出现新属性,您可以添加到对象中,而无需修改现有的工厂方法。
答案 5 :(得分:0)
似乎,“是的,它是”,除了:
使用Paul Whelan建议的varargs或者使用Jon Skeet建议的具有正确默认值的字段定义一个额外类型可以实现类似的效果。鲍里斯·帕夫洛维奇(BorisPavlović)补充说,他的类型可能是一个内在的静态类,可以把东西整齐地放在正确的位置。
缺点(请注意,整个问题不是关于任何严重的影响,只是关于方便的调整):
Varargs似乎最适合传递一个可变长度的值列表,这些值列表具有非常相似的形式,并且具有大致相同的含义,例如名称列表。如果用于问题中所述的目的,该方法将必须对列表执行各种检查以便解释它,这似乎不是更多,但不太方便。
如果结果类型可以是其他用途,而不仅仅是传递给一个特定方法,或者它是一个更复杂的参数集,那么携带参数的特殊类型似乎最有用。如果有2-4个参数,有些可能有默认值,那么重载似乎更方便,但这可能是个人品味的问题。
答案 6 :(得分:0)
是的,oop的重载是在java中使用Default paramater的唯一方法。 但这是你的黑客攻击。 如果您使用重载并且您想要使用默认参数。然后你会结束
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) { }
但是使用varargs
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