2189

I came across some Java code that had the following structure:

public MyParameterizedFunction(String param1, int param2)
{
 this(param1, param2, false);
}
public MyParameterizedFunction(String param1, int param2, boolean param3)
{
 //use all three parameters here
}

I know that in C++ I can assign a parameter a default value. For example:

void MyParameterizedFunction(String param1, int param2, bool param3=false);

Does Java support this kind of syntax? Are there any reasons why this two step syntax is preferable?

Wolf
10.3k8 gold badges70 silver badges116 bronze badges
asked Jun 15, 2009 at 18:04
5
  • 119
    No. However, the Builder pattern can help. Commented May 27, 2010 at 2:58
  • 6
    @Jatin With the Eclipse "Change method signature" refactoring you can add a parameter and provide a default value that existing invokers will use. Commented Jan 12, 2015 at 15:17
  • 2
    @ErwinBolwidt Thanks. I am using Android Studio, and it also has the option of refactoring the method and providing default values. Quite useful. Commented Jan 14, 2015 at 11:40
  • Use the static factory method! Commented Jan 10, 2019 at 19:11
  • 3
    @temporary_user_name public MyParameterizedFunction(String param1, int param2) is a constructor, not method, declaration. Commented Jan 24, 2019 at 22:49

26 Answers 26

1242

No, the structure you found is how Java handles it, (that is, with overloading instead of default parameters).

For constructors, See Effective Java: Programming Language Guide's Item 1 tip (Consider static factory methods instead of constructors) if the overloading is getting complicated. For other methods, renaming some cases or using a parameter object can help.

This is when you have enough complexity that differentiating is difficult. A definite case is where you have to differentiate using the order of parameters, not just number and type.

John Smith
7,4477 gold badges52 silver badges63 bronze badges
answered Jun 15, 2009 at 18:14
2
776

No, but you can use the Builder Pattern, as described in this Stack Overflow answer.

As described in the linked answer, the Builder Pattern lets you write code like

Student s1 = new StudentBuilder().name("Eli").buildStudent();
Student s2 = new StudentBuilder()
 .name("Spicoli")
 .age(16)
 .motto("Aloha, Mr Hand")
 .buildStudent();

in which some fields can have default values or otherwise be optional.

answered Jun 15, 2009 at 19:20
6
  • 25
    Im curious though, why do we need a builder class when using the builder pattern. I was thinking of Student s1 = new Student().name("Spicolo").age(16).motto("Aloha, Mr Hand); Commented Feb 14, 2013 at 8:32
  • 73
    @ivanceras: It's relevant when classes have required fields, and you don't want to be able to instantiate those classes in an invalid state. So if you just said Student s1 = new Student().age(16); then that would leave you with a Student without a name, which might be bad. If it's not bad, then your solution is fine. Commented Feb 14, 2013 at 18:33
  • 71
    @ivanceras: another reason is you might want your class to be immutable after construction, so you wouldn't want methods in it that change its values. Commented Feb 27, 2013 at 16:02
  • 5
    @ivanceras: I used Builders for 3 things - eliminating the multiple argument and fluent initialization, immutability and most importantly I feel to validate the domain object in the build() method.Why create an object instance if is invalid.You can also overload static factory methods like in the above case buildFreshman(), buildSenior() etc Commented Aug 16, 2015 at 22:00
  • 1
    The use of the Builder pattern here seems rather superfluous for what the OP is asking (default parameter values.) As a matter of fact, I don't see how this provides an answer to the original question at all. Commented Jan 3, 2019 at 17:02
381

Sadly, no.

answered Jun 15, 2009 at 18:05
5
  • 36
    Is it so sad? Doing so would introduce potentially ambiguous function signatures. Commented Jun 15, 2009 at 19:46
  • 87
    @Trey: languages with default parameters often ditch function overloading since it is then less compelling. So no ambiguity. Beside, Scala added the feature in 2.8, and somehow solved the ambiguity issue (since they kept the overloading for compatibility reasons). Commented May 24, 2011 at 13:09
  • 2
    I believe parameter defaults are bad practice and overloading is a much cleaner solution. You can even hide the default constructor and use static factory methods to return initialized instances. This is also useful for IOC, where you determine the implementation of the interface to return. If you want to optionally assign a property, create a public property, or overload a constructor Having another way to perform the same function does not make it better. It just makes the language more cryptic and is simply lazy programming when this is one of the reasons for function overloading. Commented Nov 14, 2013 at 18:58
  • 50
    I fail to see how parameter defaults prevent function overloading. C# for instance allows overrides and also allows for default initializes. Seems like arbitrary choice, not restriction is the reason. Commented Nov 30, 2013 at 17:43
  • 5
    Works in C# for many years now without problems, even combined with method overloading. Compiler shows a warning on conflicts and that's it. Just do something like writeToFile(String content, boolea append=false); Commented Oct 13, 2016 at 15:21
94

Unfortunately, yes.

void MyParameterizedFunction(String param1, int param2, bool param3=false) {}

could be written in Java 1.5 as:

void MyParameterizedFunction(String param1, int param2, Boolean... params) {
 assert params.length <= 1;
 bool param3 = params.length > 0 ? params[0].booleanValue() : false;
}

But whether or not you should depend on how you feel about the compiler generating a

new Boolean[]{}

for each call.

For multiple defaultable parameters:

void MyParameterizedFunction(String param1, int param2, bool param3=false, int param4=42) {}

could be written in Java 1.5 as:

void MyParameterizedFunction(String param1, int param2, Object... p) {
 int l = p.length;
 assert l <= 2;
 assert l < 1 || Boolean.class.isInstance(p[0]);
 assert l < 2 || Integer.class.isInstance(p[1]);
 bool param3 = l > 0 && p[0] != null ? ((Boolean)p[0]).booleanValue() : false;
 int param4 = l > 1 && p[1] != null ? ((Integer)p[1]).intValue() : 42;
}

This matches C++ syntax, which only allows defaulted parameters at the end of the parameter list.

Beyond syntax, there is a difference where this has run time type checking for passed defaultable parameters and C++ type checks them during compile.

answered May 26, 2010 at 21:51
3
  • 11
    One should never use an assert in production code. Throw an exception. Commented Oct 1, 2013 at 18:52
  • 1
    Boolean != boolean... Boolean.class.isInstance(p[0]); can be written as p[0] instanceof Boolean... Commented Feb 21, 2015 at 18:36
  • 8
    -1 This really isn't what varargs is for. This is a hack. -- in this case, using overloads will be way more readable (which is unfortunate, since three extra characters is more readable than 5 extra lines of source...). -- but Java does not support default parameters. Commented Apr 18, 2015 at 18:43
52

No, but you can very easily emulate them. What in C++ was:

public: void myFunction(int a, int b=5, string c="test") { ... }

In Java, it will be an overloaded function:

public void myFunction(int a, int b, string c) { ... }
public void myFunction(int a, int b) {
 myFunction(a, b, "test");
}
public void myFunction(int a) {
 myFunction(a, 5);
}

Earlier was mentioned, that default parameters caused ambiguous cases in function overloading. That is simply not true, we can see in the case of the C++: yes, maybe it can create ambiguous cases, but these problem can be easily handled. It simply wasn't developed in Java, probably because the creators wanted a much simpler language as C++ was - if they had right, is another question. But most of us don't think he uses Java because of its simplicity.

4
  • 12
    The main idea of C# default value notation is precisely to avoid this boilerplate coding and have just one constructor instead of many. Commented Oct 17, 2017 at 9:27
  • 1
    @KolyaIvankov I don't know C#, but I know C++ where the reasoning is the same. I don't know what is the better, but I think, actually the same boilerplate code is generated by the compiler in the case of C++/C# and it is going into the final binary. Commented Oct 17, 2017 at 9:34
  • 10
    Every programming language is (in particular) a means to avoid an Assembler boilerplate, am I wrong? The question is only whether it gives a handy functionality, or not. Commented Oct 17, 2017 at 11:45
  • 3
    Being more specific: languages are tools that allow us to write programs in a way we can have control over what is written, compiling is a way to tell a machine what we want from it. A tool is more useful if it allows us to avoid boilerplate. In effect, gnavi asked, if they can avoid precisely the type of boilerplate code you propose as an answer, since C# allows for it. Commented Oct 17, 2017 at 13:50
28

You can do this is in Scala, which runs on the JVM and is compatible with Java programs. http://www.scala-lang.org/

i.e.

class Foo(var prime: Boolean = false, val rib: String) {}
om-nom-nom
62.9k13 gold badges186 silver badges231 bronze badges
answered Jul 21, 2011 at 16:26
2
  • 71
    Bring whole new language to get one not so common feature? Commented Apr 3, 2012 at 13:59
  • 12
    that has nothing to do with the OP's question Commented Nov 7, 2016 at 15:45
25

Instead of using:

void parameterizedMethod(String param1, int param2) {
 this(param1, param2, false);
}
void parameterizedMethod(String param1, int param2, boolean param3) {
 //use all three parameters here
}

You could utilize java's Optional functionality by having a single method:

void parameterizedMethod(String param1, int param2, @Nullable Boolean param3) {
 param3 = Optional.ofNullable(param3).orElse(false);
 //use all three parameters here
}

The main difference is that you have to use wrapper classes instead of primitive Java types to allow null input.Boolean instead of boolean, Integer instead of int and so on.

answered Feb 14, 2020 at 11:52
3
  • 1
    i tried but still need to pass params3 into function for avoid warning error from android studio Commented Sep 14, 2021 at 4:55
  • What's the necessary imports for Nullable and Optional? Commented Aug 12, 2022 at 8:59
  • import java.util.Optional; and import javax.annotation.Nullable; Commented Nov 17, 2022 at 15:29
21

No, but the simplest way to implement this is:

public myParameterizedFunction(String param1, int param2, Boolean param3) {
 param3 = param3 == null ? false : param3;
}
public myParameterizedFunction(String param1, int param2) {
 this(param1, param2, false);
}

or instead of the ternary operator, you can use if:

public myParameterizedFunction(String param1, int param2, Boolean param3) {
 if (param3 == null) {
 param3 = false;
 }
}
public myParameterizedFunction(String param1, int param2) {
 this(param1, param2, false);
}
answered Nov 22, 2017 at 18:13
0
20

I might be stating the obvious here but why not simply implement the "default" parameter yourself?

public class Foo() {
 public void func(String s){
 func(s, true);
 }
 public void func(String s, boolean b){
 //your code here
 }
}

for the default, you would either use

func("my string");

and if you wouldn't like to use the default, you would use

func("my string", false);
OmG
19k13 gold badges69 silver badges96 bronze badges
answered Feb 18, 2013 at 13:59
3
  • 19
    The poster asked if this (rather ugly) pattern can be avoided ... ;-) In more modern languages (like c#, Scala) you don't need this extra overloads which only creates more lines of code. Up to some point you can use varargs in the meantime (static int max( int... array ) { }), but they are only a very ugly workaround. Commented Feb 18, 2013 at 14:10
  • 2
    Overloading is not ugly and has many benefits, such as different method calls with different signatures can perform different functionality. //This is better public class Foo() { /* This does something */ public void func(String s){ //do something } /* This does something else with b */ public void func(String s, boolean b){ // b was passed } } //Than this public class Foo() { /* This does something unless b = value, then it does something else */ public void func(String s, boolean b = value){ If (b){ // Do Something } else{ // Do something else } } } Commented Nov 14, 2013 at 19:57
  • 1
    @Offler default parameters have nothing to do with "modern language". I used them in Delphi 20 years ago and they probably already existed in Turbo Pascal. Commented Apr 6, 2017 at 13:09
11

It is not supported in java as in other language for ex. Kotlin.

answered Dec 15, 2019 at 17:11
0
10

As Scala was mentioned, Kotlin is also worth mentioning. In Kotlin function parameters can have default values as well and they can even refer to other parameters:

fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size) {
 ...
}

Like Scala, Kotlin runs on the JVM and can be easily integrated into existing Java projects.

answered Nov 26, 2017 at 19:51
6

No. In general Java doesn't have much (any) syntactic sugar, since they tried to make a simple language.

answered Jun 15, 2009 at 18:49
3
  • 31
    Not quite. The bitter truth is that the team was on a tight schedule and had no time for syntactic sugar. Why else would const and goto be reserved keywords which no implementation? — Especially const is something I miss bitterly — final is no replacement and they knew it. — And if you made the concious decision to never implement goto you won't need to reserve the keyword. — And later in the Java Team cheated by making the Label based break and continue as powerful as a Pascal goto. Commented Sep 18, 2011 at 12:46
  • "Simple, Object-Oriented and Familiar" was indeed a design goal - see oracle.com/technetwork/java/intro-141325.html Commented Sep 2, 2013 at 9:27
  • 1
    tomjen said: "No. In general Java doesn't have much (any) syntactic sugar, since they tried to make a simple language". So you are saying that removing a lot of unnecessary features from C++ makes a Java a simple language, then tell me why Java does have variadic methods? Why does it have varargs? It is not needed if you can simply use an array of objects instead, am I right? So varargs can be removed from the language, because it is unnecessary. This will make Java more simple than what it is now. Am I right? Overloading also can be removed, because you have infinite names for each method. Commented Aug 8, 2017 at 15:58
6

No.

You can achieve the same behavior by passing an Object which has smart defaults. But again it depends what your case is at hand.

Peter Mortensen
31.5k22 gold badges110 silver badges134 bronze badges
answered Jun 15, 2009 at 18:16
4

It is not supported but there are several options like using parameter object pattern with some syntax sugar:

public class Foo() {
 private static class ParameterObject {
 int param1 = 1;
 String param2 = "";
 }
 public static void main(String[] args) {
 new Foo().myMethod(new ParameterObject() {{ param1 = 10; param2 = "bar";}});
 }
 private void myMethod(ParameterObject po) {
 }
}

In this sample we construct ParameterObject with default values and override them in class instance initialization section { param1 = 10; param2 = "bar";}

answered Dec 13, 2012 at 17:09
0
4

You may use Java Method Invocation Builder to automatically generate the builder with default values.

Just add @GenerateMethodInvocationBuilder to the class, or interface, and the @Default to parameters in methods where you want default values. A builder will be generated at compile time, using the default values that you specified with your annotations.

@GenerateMethodInvocationBuilder
public class CarService {
 public CarService() {
 }
 public String getCarsByFilter(//
 @Default("Color.BLUE") Color color, //
 @Default("new ProductionYear(2001)") ProductionYear productionYear,//
 @Default("Tomas") String owner//
 ) {
 return "Filtering... " + color + productionYear + owner;
 }
}

And then you can invoke the methods.

CarService instance = new CarService();
String carsByFilter = CarServiceGetCarsByFilterBuilder.getCarsByFilter()//
 .invoke(instance);

Or set any of the default values to something else.

CarService instance = new CarService();
String carsByFilter = CarServiceGetCarsByFilterBuilder.getCarsByFilter()//
 .withColor(Color.YELLOW)//
 .invoke(instance);
answered Jun 11, 2016 at 18:28
4

If you really want to, you can check it manually by using null:

public MyParameterizedFunction(String param1, int param2, boolean param3)
{
 if(param3 == null) {
 param3 = false;
 }
}

However i heavily recommend using something else, like overloading or a static factory. Maybe you can get away with this, but it can lead to unexcspected behavior. For example you could have an error in your code, so that your boolean never gets a value. In this case you would not get a NullPointerException. Instead it will look like it was set to false, which can be very confusing to debug.

answered Oct 20, 2020 at 10:45
3

Try this solution:

public int getScore(int score, Integer... bonus)
{
 if(bonus.length > 0)
 {
 return score + bonus[0];
 }
 return score;
}
answered Nov 3, 2013 at 8:36
3

constructor like for method

static void popuping() {
 popuping("message", "title");
}
static void popuping(String message) {
 popuping(message, "title");
}
static void popuping(String message, String title){
 JOptionPane.showMessageDialog(null, message,
 title, JOptionPane.INFORMATION_MESSAGE);
}
answered Oct 5, 2021 at 1:05
0
2

A similar approach to https://stackoverflow.com/a/13864910/2323964 that works in Java 8 is to use an interface with default getters. This will be more whitespace verbose, but is mockable, and it's great for when you have a bunch of instances where you actually want to draw attention to the parameters.

public class Foo() {
 public interface Parameters {
 String getRequired();
 default int getOptionalInt(){ return 23; }
 default String getOptionalString(){ return "Skidoo"; }
 }
 public Foo(Parameters parameters){
 //...
 }
 public static void baz() {
 final Foo foo = new Foo(new Person() {
 @Override public String getRequired(){ return "blahblahblah"; }
 @Override public int getOptionalInt(){ return 43; }
 });
 }
}
answered Jul 14, 2016 at 17:58
2

I've now spent quite some time to figure out how to use this with methods that return values, and I haven't seen any examples so far, I thought it might be useful to add this here:

int foo(int a) {
 // do something with a
 return a;
}
int foo() {
 return foo(0); // here, 0 is a default value for a
}
answered Mar 12, 2019 at 12:17
0
1

This is how I did it ... it's not as convenient perhaps as having an 'optional argument' against your defined parameter, but it gets the job done:

public void postUserMessage(String s,boolean wipeClean)
{
 if(wipeClean)
 {
 userInformation.setText(s + "\n");
 }
 else
 {
 postUserMessage(s);
 }
}
public void postUserMessage(String s)
{
 userInformation.appendText(s + "\n");
}

Notice I can invoke the same method name with either just a string or I can invoke it with a string and a boolean value. In this case, setting wipeClean to true will replace all of the text in my TextArea with the provided string. Setting wipeClean to false or leaving it out all together simply appends the provided text to the TextArea.

Also notice I am not repeating code in the two methods, I am merely adding the functionality of being able to reset the TextArea by creating a new method with the same name only with the added boolean.

I actually think this is a little cleaner than if Java provided an 'optional argument' for our parameters since we would need to then code for default values etc. In this example, I don't need to worry about any of that. Yes, I have added yet another method to my class, but it's easier to read in the long run in my humble opinion.

answered Jan 18, 2015 at 15:40
1

NO, But we have alternative in the form of function overloading.

called when no parameter passed

void operation(){
int a = 0;
int b = 0;
} 

called when "a" parameter was passed

void operation(int a){
int b = 0;
//code
} 

called when parameter b passed

void operation(int a , int b){
//code
} 
answered Sep 1, 2016 at 6:51
1

There are half a dozen or better issues such as this, eventually, you arrive at the static factory pattern ... see the crypto API for that. Sort difficult to explain, but think of it this way: If you have a constructor, default or otherwise, the only way to propagate state beyond the curly braces is either to have a Boolean isValid; ( along with the null as default value v failed constructor ) or throw an exception which is never informative when getting it back from field users.

Code Correct be damned, I write thousand line constructors and do what I need. I find using isValid at object construction - in other words, two-line constructors - but for some reason, I am migrating to the static factory pattern. I just seem you can do a lot if you in a method call, there are still sync() issues but defaults can be 'substituted' better ( safer )

I think what we need to do here is address the issue of null as default value vis-a-vis something String one=new String(""); as a member variable, then doing a check for null before assigning string passed to the constructor.

Very remarkable the amount of raw, stratospheric computer science done in Java.

C++ and so on has vendor libs, yes. Java can outrun them on large scale servers due to it's a massive toolbox. Study static initializer blocks, stay with us.

OmG
19k13 gold badges69 silver badges96 bronze badges
answered Sep 23, 2009 at 0:44
1

One idea is to use String... args

public class Sample {
 void demoMethod(String... args) {
 for (String arg : args) {
 System.out.println(arg);
 }
 }
 public static void main(String args[] ) {
 new Sample().demoMethod("ram", "rahim", "robert");
 new Sample().demoMethod("krishna", "kasyap");
 new Sample().demoMethod();
 }
}

Output

ram
rahim
robert
krishna
kasyap

from https://www.tutorialspoint.com/Does-Java-support-default-parameter-values-for-a-method

answered Jul 25, 2020 at 8:17
0

You can use the following-

public void mop(Integer x) {
 // Define default values
 x = x == null ? 200 : x;
}
answered Dec 30, 2019 at 7:50
0

The Straight answer is no.

These answers are pretty old and mainly discuss the alternatives we can have even if java doesn't have a straight way of the default method parameter.

we can deal with this scenario easily with functional Programming in java.

we can utilize the method currying of java functional programming and I think it can be best utilized for such scenarios where we need to have default parameters.

we may need a default parameter in the following situations... Example: Create a method that works on Two different objects and returns the computation

int mutiply(int a,int b){
 return a*b;
 }

if we want to have a method to get multiply by 2, we will have to Override the method like below

int mutiply(int a){
 mutiply(a, 2); // as can not write mutiply(int a,b=2)
 }

Above, 2 is a default value for b, but it's going to be fixed. what if we want to have multiplied by three, now we cannot overload this further and it does feel odd to have multiple methods like this.

This is when we can utilize the method currying technique.

method Currying is the way of converting multi-parameter functions into multiple functions each accepting a single parameter.

Steps to create a Curried method

  1. Write a function that accepts a single parameter and returns another function, like below.

     Function<Integer,Function<Integer,Integer>> mutiply = a->{
     return b -> a*b;
     };
    
  2. Let's Simplify and understand the above method.

The Above method accepts only One integer Argument and returns another function with one parameter a as the default value and b as a variable. In case you are confused and start thinking how the method can use a variable from the caller function and don’t know about closures ...

"A closure is a function that refers to a free variable in its lexical context." So here, in this case, closure is the returned function when operated on variable multiply and it has a free variable a that has the lexical context of the caller function.

  1. Return the multiply method or fix the default value for one of the parameters.

     //multiply is defined in the first step
     mutiplyByTwo = mutiply.apply(2)
     mutiplyByThree = mutiply.apply(3);
     mutiplyByFour = mutiply.apply(4);;
    

    And so on ...

  2. Pass the second variable to the returned function to get the result.

    mutiplyByTwo.apply(2);//results 
    mutiplyByTwo.apply(3);//results 6
     mutiplyByThree.apply(2);//results 6
     mutiplyByThree.apply(3);//results 9
     mutiplyByFour.apply(2);//results 8
     mutiplyByFour.apply(3);//results 124
    

You can find my original post here ... https://www.linkedin.com/pulse/can-we-have-default-method-parameter-java-rajat-singh/?trackingId=yW84I1fzT6WGStrNPAWn4w%3D%3D

answered Dec 21, 2022 at 9:12
0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.