views:

424

answers:

6

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.

+2  A: 

see varargs

http://java.sun.com/developer/JDCTechTips/2005/tt0104.html#1

Paul Whelan
Seems as an abuse of the varargs feature to me.
erikkallen
+1 to erikkallen's comment.
Jon Skeet
I feel varargs are good if the arguments vary in number but all mean the same, as with the list of names in those examples. If the arguments mean something different, you soon have to put in so many checks that it's actually cleaner and easier to overload. Right?
Hanno Fietz
Please explain further thanks guys
Paul Whelan
Hanno has already explained it. varargs is for those situations where each argument is "another one of the same thing" - for example Arrays.asList(T ...).
oxbow_lakes
Sorry ye Hanno Posted the same time I was replying just noticed it now
Paul Whelan
+6  A: 

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.

Jon Skeet
Yeah, this might be good for some situations, I'll keep it in mind. However, if I end up with a type that's only useful as an argument for a single method, I think it's a little too awkward. I'll stick to overloading for those.
Hanno Fietz
@Hanno Fietz you may declare the type as static inner class in the object where the method had been declared. Do not hesitate to create types. They are for free in Java :)
Boris Pavlović
Nice hint too, Boris. Thanks.
Hanno Fietz
A: 

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.

siddhadev
A: 

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.

Hanno Fietz
+1  A: 

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?

TofuBeer
+1 for the last comment
Mario Ortegón
"My advice, for your Java coding learn to program like a Java developer rather than a PHP developer." - +1 for this. Sounds like the focus is too much on functions and parameters passed in rather than objects and internal state.
duffymo
Don't get me wrong on this, I sure don't mind different concepts in languages, I carefully chose Java for this project and I'm happy with my choice. I was mainly wondering whether this is the language or some misunderstanding on my side.
Hanno Fietz
can you give sample code (psueduo is fine) for the factory example?
TofuBeer
+2  A: 

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

Scott Stanchfield
That's cool. Although it makes me wonder why there isn't something like that in the language already.
Hanno Fietz