Matthew is a DZone employee and has posted 155 posts at DZone. You can read more from them at their website. View Full User Profile

Borrowing Language Features - Default Argument Values in Java

03.28.2008
| 28750 views |
  • submit to reddit

I've been doing a lot of coding in other languages lately, primarily PHP with some Ruby thrown in there, in addition to my regular Java coding and there's one feature that I've been missing from my Java code...

In PHP, I've come to really enjoy being able to add another argument to a method and give it a default value, instantly providing backwards compatibility without needing to add another method that calls yet another method with a default value. Take the following two snippets of code for example:

Java:

public void methodA(String arg1, String arg2) {
methodA(arg1, arg2, "default");
}

public void methodA(String arg1, String arg2, String arg3) {
// Do something to the arguments there
}

PHP:

function funcA($arg1, $arg2, $arg3 = 'default') {
// Do more here
}

In our last Javalobby Newsletter, the author argued that Lines of Code is a bad argument, and I tend to agree. My reasoning here isn't because I'm lazy and don't like more lines of code. My argument is that the PHP option is easier to maintain, given that there is only one function. Given Java's speed, what does a function call cost? Is it more expensive to call 2 methods than just a single one?

I'm not saying that this style is for everyone, but I know I would benefit from it. I've seen my share of weirdness from PHP lately, and it has made me appreciate Java and the speed and stability of a Java server more than I ever did before (for example, I never thought that a Java app server was light on memory use :)). Other languages often have nice things we can borrow from them, and I think that this is one of them. What do you think?

Comments

Mr B Loid replied on Fri, 2008/03/28 - 6:36am

I would rather have this than almost every other "new feature" suggested so far...  It's the one thing I *still* miss from my Delphi days (and that was almost 10 years ago)

Mikael Grev replied on Fri, 2008/03/28 - 8:30am

Yes!!  I really want this as well. It would clean up a lot of APIs, new ones at least. A no-brainer to me.

Henry Brown replied on Fri, 2008/03/28 - 8:32am

My thoughts on this topic is exactly like yours. The java developers I've discussed this with tend to agree with that view or tend not to mind it either way. I'm hoping there's some good responses that indicate why such a feature should not be allowed.

Artur Biesiadowski replied on Fri, 2008/03/28 - 9:31am

There is one quite important difference between java and other languages as far as default arguments are concerned. In all the other cases (I know about), default arguments are resolved on compile time (so it is just compiler trickery, which inserts missing arguments behind the scenes). To follow 'java way' default arguments in java would have to work differently - you would be really calling function with some arguments missing and they would be filled out at call/link time.

Why it makes a difference? Think about 3rd party library, exporting function doSomething(String name). In next release, they want to add doSomething(String name, boolean ignoreCase = false). Currently, they will just export two methods (one for backward compatibility). With java style defaults, they can just change the function by adding a parameter with default value and all existing program will continue to work.

Unfortunately, to get a full power of that, we need named arguments - and named arguments are not so easy to get inside 'mature' language. I would prefer to rather wait some more time for named arguments, rather than having C++ style, compile-time only defaults soon.

Mark Thornton replied on Fri, 2008/03/28 - 10:11am

Microsoft docs:

 Use method overloading instead of allowing default arguments. Default arguments do not version well and therefore are not allowed in the Common Language Specification (CLS).

 From here: http://msdn2.microsoft.com/en-us/library/xxfyae0c(VS.71).aspx

 I seem to remember some programming puzzlers from people who combined method overloading and default arguments in C++.

Karim Elsayed replied on Fri, 2008/03/28 - 10:52am

I agree about borrowing useful features from other languages,  but not this one :)

 default arguments are handy when it comes to primitives which are passed by value, and also to immutable objects like String in your example.

 but how do you want it to work for normal mutable objects?

 should a new object be created automatically? if yes , which constructor to use

so I think default arguments is really asking for troubles

The alternative is to do something like this, it might not be very readible but at least you have control:

 

public void methodA(String arg1, String arg2, String arg3) {  
arg3=  arg3 != null ? arg3 : "default";    
}  
 

The overloading is also okay but in case you need default values for multiple arguments you will end up creating having many methods with  all possible combination of default arguments, for the example you use imagine you want to have a default value for the 3 arguments. you will end up with this

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

 imagine with four arguments!

 this is probably easier although not very sexy

public void methodA(A arg1, B arg2, C arg3) {  

arg1=  arg1 != null ? arg1 : new A();
arg2=  arg2 != null ? arg2 :  new B();
arg3=  arg3 != null ? arg3 : "new C();


}

 

 

 

 

Mikael Grev replied on Fri, 2008/03/28 - 11:46am in response to: Karim Elsayed

Maybe we don't need the ultimate flexibility on this one. Maybe only immutable objects, like for default values in annotations, and/or require a final method declararion.

Cheers
Mikael

Henry Brown replied on Fri, 2008/03/28 - 12:09pm in response to: Karim Elsayed

Personally I prefer using overloading to fake the default argument property simply because it requires less work from the caller whereas the null checking solution requires the same amount of work from the caller to call the method: 

methodA(null,null,null);

and in my opinion, passing null values to methods makes it harder to understand the code. I agree that it need not be an all or nothing approach - It could simply be that default values are allowed for anything that can be defined as a literal (as in the restriction that a vararg must be the last parameter). However, I also don't see why you could not specify default values by calling a constructor explicitly:


void methodA(Date date = new Date()) {}

void methodB(Person p = new Person("John", "Doe")) {}

 


 

Mike P(Okidoky) replied on Fri, 2008/03/28 - 1:36pm

I ran into the following problem before when I was trying to argue for named arguments.  eg:

<code>
int method(int x = 0, int y = 0, int w = 320, int h=240)
...
method(w: 640, h: 480);
</code>

In addition to the default arguments, it makes it very clear what parameters you're trying to pass in.

Great alternative to calls like this: something(0, null, null, null, 0, "something", "something else").
What the heck is what?

But, one of the problems was that where should the code go where the default is set?  The method or the calling method?  If it goes in the calling method, then the default value needs to described in the class file.  It could be annotation that an updated javac compiler would automatically create for you I suppose.

But what if that third party library changes and the default parameter changes.  Or what if the default parameter is removed and is not optional anymore?  Now you have code that still runs, but can't be recompiled.

There were some other arguments against it, one in particular, just can't remember what... 

Stefan Schulz replied on Sat, 2008/03/29 - 4:38am

The idea for optional parameters is not new and has been discussed in many variations. The comments I've read mix up two things (that maybe related though): optional parameters and readability (e.g. named parameters).

Current Java already has "optional" parameters in form of Varargs. The naive approach (no language change) would be to pass optional parameters within that Vararg and unpack them at method side. This would of course cause a lot of boiler plate and it's not type safe.

One could make the compiler handle that boilerplate and interpret defaulted parameters as part of a Varargs parameter. The compiler would wrap arguments into the Vararg array at invocation time (including autoboxing primitives to allow for null) and unwrap those arguments having a corresponding parameter within the invoked method. This would overcome some of the issues mentioned wrt. signature changes and be compatible to current Java at bytecode level.

Mike P(Okidoky) replied on Sat, 2008/03/29 - 11:09am in response to: Stefan Schulz

But it would impact performance when passing primitives.

William Houghtaling replied on Mon, 2011/07/04 - 9:11am

Burrowing languages is alright and it is useful in some other way but for me it is not certain that it would work all the time. Burrowing languages could sometime make other codes or the burrowed languages could have some errors on them. In the previous comments they tackle some of the method that should we encounter when burrowing and when we will use the default values. Gauthier, Houghtaling and Williams

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.