Categories
default-parameters java methods overloading parameters

Does Java support default parameter values?

1984

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?

7

  • 109

    No. However, the Builder pattern can help.

    May 27, 2010 at 2:58


  • 83

    I really miss this feature. It helps a lot when modifying existing code to take extra parameter to a function or constructor

    – Jatin

    Jan 1, 2015 at 7:25


  • 5

    @Jatin With the Eclipse “Change method signature” refactoring you can add a parameter and provide a default value that existing invokers will use.

    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.

    – Jatin

    Jan 14, 2015 at 11:40

  • 3

    @temporary_user_name public MyParameterizedFunction(String param1, int param2) is a constructor, not method, declaration.

    Jan 24, 2019 at 22:49

1146

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.

6

  • 31

    this was in 2009, static anything is pretty much considered harmful in 2015. Type safe fluent Builder instances that enforce complete and valid construction contracts are a much better solution now.

    – user177800

    Dec 18, 2015 at 4:27


  • 173

    @JarrodRoberson: Static factory methods are no more harmful than new. They are used all the time in new code. Builders for simple value objects are often the result of over-engineering.

    – Lii

    Jan 22, 2016 at 8:38


  • 13

    @JarrodRoberson: Interesting way of forcing correct use via the compiler, thanks for sharing! Friendly suggestion for future posts: 300 lines of uncommented source code is probably a bit much to digest for most people (code is harder to read than to write, after all). Thanks again!

    Jan 27, 2016 at 21:55

  • 17

    @JarrodRoberson: Nice, looking forward to it! What I wanted to communicate: as a reader of your blog, a 50 line example with a brief text description of what’s going on would help me more than 300 lines without context.

    Jan 27, 2016 at 22:12

  • 14

    @user177800 Disagree – static methods if written as pure functions are perfectly fine. It’s when a static function mutates state that they become a problem…

    Dec 18, 2018 at 3:47

749

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.

9

  • 165

    Finally e great less-than-2-pages example of the Builder pattern.

    Nov 8, 2012 at 21:38

  • 18

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

    – ivanceras

    Feb 14, 2013 at 8:32

  • 64

    @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.

    Feb 14, 2013 at 18:33

  • 68

    @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.

    – Jules

    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

    Aug 16, 2015 at 22:00

601

There are several ways to simulate default parameters in Java:

  1. Method overloading.

    void foo(String a, Integer b) {
        //...
    }
    
    void foo(String a) {
        foo(a, 0); // here, 0 is a default value for b
    }
    
    foo("a", 2);
    foo("a");
    

    One of the limitations of this approach is that it doesn’t work if you have two optional parameters of the same type and any of them can be omitted.

  2. Varargs.

    a) All optional parameters are of the same type:

    void foo(String a, Integer... b) {
        Integer b1 = b.length > 0 ? b[0] : 0;
        Integer b2 = b.length > 1 ? b[1] : 0;
        //...
    }
    
    foo("a");
    foo("a", 1, 2);
    

    b) Types of optional parameters may be different:

    void foo(String a, Object... b) {
        Integer b1 = 0;
        String b2 = "";
        if (b.length > 0) {
          if (!(b[0] instanceof Integer)) { 
              throw new IllegalArgumentException("...");
          }
          b1 = (Integer)b[0];
        }
        if (b.length > 1) {
            if (!(b[1] instanceof String)) { 
                throw new IllegalArgumentException("...");
            }
            b2 = (String)b[1];
            //...
        }
        //...
    }
    
    foo("a");
    foo("a", 1);
    foo("a", 1, "b2");
    

    The main drawback of this approach is that if optional parameters are of different types you lose static type checking. Furthermore, if each parameter has different meaning you need some way to distinguish them.

  3. Nulls. To address the limitations of the previous approaches you can allow null values and then analyse each parameter in a method body:

    void foo(String a, Integer b, Integer c) {
        b = b != null ? b : 0;
        c = c != null ? c : 0;
        //...
    }
    
    foo("a", null, 2);
    

    Now all arguments values must be provided, but the default ones may be null.

  4. Optional class. This approach is similar to nulls, but uses Java 8 Optional class for parameters that have a default value:

    void foo(String a, Optional<Integer> bOpt) {
        Integer b = bOpt.isPresent() ? bOpt.get() : 0;
        //...
    }
    
    foo("a", Optional.of(2));
    foo("a", Optional.<Integer>absent());
    

    Optional makes a method contract explicit for a caller, however, one may find such signature too verbose.

  5. Builder pattern. The builder pattern is used for constructors and is implemented by introducing a separate Builder class:

     class Foo {
         private final String a; 
         private final Integer b;
    
         Foo(String a, Integer b) {
           this.a = a;
           this.b = b;
         }
    
         //...
     }
    
     class FooBuilder {
       private String a = ""; 
       private Integer b = 0;
    
       FooBuilder setA(String a) {
         this.a = a;
         return this;
       }
    
       FooBuilder setB(Integer b) {
         this.b = b;
         return this;
       }
    
       Foo build() {
         return new Foo(a, b);
       }
     }
    
     Foo foo = new FooBuilder().setA("a").build();
    
  6. Maps. When the number of parameters is too large and for most of them default values are usually used, you can pass method arguments as a map of their names/values:

    void foo(Map<String, Object> parameters) {
        String a = ""; 
        Integer b = 0;
        if (parameters.containsKey("a")) { 
            if (!(parameters.get("a") instanceof Integer)) { 
                throw new IllegalArgumentException("...");
            }
            a = (String)parameters.get("a");
        } else if (parameters.containsKey("b")) { 
            //... 
        }
        //...
    }
    
    foo(ImmutableMap.<String, Object>of(
        "a", "a",
        "b", 2, 
        "d", "value")); 
    

Please note that you can combine any of these approaches to achieve a desirable result.

8

  • 2

    Good explanation. I’ve never seen return values used like this. For 5) what do the return this do? Also, doesn’t FooBuilder().setA("a").build(); since (by definition) the constructor is called first and FooBuilder() returns a value, doesn’t this mean .setA("a"): doesn’t get the chance to be called?

    – Celeritas

    Jul 18, 2014 at 22:37

  • 7

    @Celeritas return this returns the same object on which the method was called (in the example, FooBuilder). This allows chaining of methods in one statement acting on the same object: new FooBuilder().setA(..).setB(..).setC(..) etc as opposed to calling each method in a separate statement.

    – ADTC

    Aug 27, 2014 at 8:44


  • 3

    @Celeritas new FooBuilder() returns a FooBuilder object on which the setA method is called. As setB is not called, this.b retains the default value. Finally the build method is called on this FooBuilder object. The build method creates and returns a Foo object which is set to the variable Foo foo. Notice that the FooBuilder object is not stored in any variable.

    – ADTC

    Aug 27, 2014 at 8:48

  • Annotation can also be used to create default parameters and is most useful when required for polymorphic collections. docs.oracle.com/javase/tutorial/java/annotations/declaring.html

    Jan 27, 2015 at 9:47

  • 2

    Over 900 upvotes on the same answer across two questions. I’m impressed: stackoverflow.com/questions/965690/java-optional-parameters/…

    – AdamMc331

    Nov 28, 2015 at 19:19