重载真的是 Java 中获取方法参数默认值的唯一方法吗?

发布于 2024-07-14 05:24:22 字数 466 浏览 4 评论 0原文

我对 Java、Python 和 PHP 都很陌生,我习惯了函数参数的默认值。

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

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

我记得在短暂接触 C++ 和 ActionScript 时,这已经让我很恼火。 现在,更有经验的 Java 开发人员是否有一些捷径?

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

I'm quite new to Java and from Python and PHP, I'm used to default values for function parameters.

So I have a habit of writing methods that are designed to be called from slightly different situations where you want to set only some of the values. For example, in my PHP code, this would be common where I have factory methods that provide object instances with slightly different properties.

In Java, it seems, I have to have one method that expects all parameters and then several overloaded variations that would call that method with some of the parameters set to defaults and some provided by the caller. Which is, well, OK, but can get on my nerves sometimes.

I remember that this already annoyed me in some brief excursions to C++ and ActionScript. Now, do more experienced Java developers have some shortcut for this?

It seems to me that, technically, the question has been answered by the sum of all posts as "Yes, it is". I've opened a wiki post below to collect the various alternative solutions, please contribute if you like. I found all of these very helpful as an inspiration and as learning examples for typical Java constructs.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

本宫微胖 2024-07-21 05:24:22

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

您可以在标准库中使用 ProcessBuilder处理类。

Another option is a variation on the builder pattern - you have a type which represents all the parameters, construct an instance of that type (which defaults accordingly), set the properties you want, and then pass the result into the original method, or add a method in the "parameter type" to call the method for you.

You can see this in action in the standard libraries, with the ProcessBuilder and Process classes.

老旧海报 2024-07-21 05:24:22

请参阅 varargs

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

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

see varargs

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

(Updated URL; this comment added because stackoverflow requires >30 chars)

尴尬癌患者 2024-07-21 05:24:22

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

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/注释
——斯科特

To make this simpler, I created an annotation for default values and an annotation processor that generates a superclass with the overloaded methods. For example:

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

which generates (in a generated superclass)

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

See http://code.google.com/p/javadude/wiki/Annotations
-- Scott

别念他 2024-07-21 05:24:22

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

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

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

在 C++ 的早期,人们试图说服 C++ 表现得像 Smalltalk……但效果不太好。 在早期,如果 Java 人们尝试将他们的 C++ 知识运用到 Java 中……结果并不太理想(这令人倍感沮丧,因为这些语言表面上非常相似)。

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

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

It can be very hard to try to translate your though process from one langauge to another. You can, as others have pointed out, do some work arounds to maybe get what you want... but the sooner you "accept" the way that Java is designed to work the better off you will be when working in Java.

I have had to do some PHP stuff... annoyed me to no end that I couldn't get it to do what I wanted... so it goes both ways.

The biggest obstacle you are going to run into is likely the static typing. There are things you can try to do to work around it, but in the end they will be a very large hack.

In the early days of C++ people tried to convince C++ to behave like Smalltalk... didn't work out too well. In the early days if Java people tried to take their C++ knowledge and use it in Java... didn't work out too well (which is doubly frustrating as the languages are very similar on the surface).

My advice, for your Java coding learn to program like a Java developer rather than a PHP developer.

For your immediate problem, is it possible that you should really be retuning differnt classes from the factory instead of creating the same kind of object with differnt variables set?

吃素的狼 2024-07-21 05:24:22

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

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

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

As long as you code in an OO manner you won't miss default values in Java. Default arguments are handy only in procedural coding style.

In OO instead of passing the state through the methods/procedures, the state is already in the object you call, or the objects you pass as parameters. Most of the time you need no more than 1 or 2 parameters in your methods.

If you want to configure you object before using it, you would construct it with a simple constructor, and than call different setters. This makes the code much more readable (because you see the setter names), compared to calling a constructor having many arguments.
And in the case a new attribute comes later, you can added to your object without having to modify your existing factory methods.

你是年少的欢喜 2024-07-21 05:24:22

看起来“是的,确实如此”,除了:

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

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

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

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

It seems like, "Yes, it is", except:

Similar effects could be achieved with varargs as suggested by Paul Whelan or by defining an extra type carrying the parameters as fields with the proper default values as suggested by Jon Skeet. Boris Pavlović adds that his type could be an inner static class to keep things neatly in the right place.

Cons (Note that this whole question is not about any serious implications, just about convenient tweaks):

Varargs seem most suitable for passing a variable-length list of values that have very similar form and mostly equivalent meaning, such as a list of names. If used for the purpose stated in the question, the method would have to perform various checks on the list in order to interpret it, which seems not more, but less convenient.

A special type carrying the parameters seems most useful if the resulting type could be of other uses than just being passed to one particular method, or when it is a more complex set of parameters. If there's 2-4 parameters and some may have default values, it still seems a little more convenient to overload, but that might be a matter of personal taste.

愛放△進行李 2024-07-21 05:24:22

是的,oop 的重载是在 java 中使用默认参数的唯一方法。
但这是给你的窍门。
如果您使用重载并且希望有默认参数。 然后你最终会

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-默认参数值

Yes by oop's its the overloading which is the only way for using Default paramater in java .
But here's the hack for you .
If you use overloading and you want to have default parameter . Then you will end up

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

But by using 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);
 }
}

The above code output will be

false
true

For more simliar examples and explanation visit java-default-parameter-values

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文