Question

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.

Was it helpful?

Solution 6

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.

OTHER TIPS

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.

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)

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

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?

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.

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top