Does Java have default parameters?

Short answer: No.

Fortunately, you can simulate them.

Many programming languages like C++ or modern JavaScript have a simple option to call a function without providing values for its arguments. In Java, default method parameters require a bit more typing to achieve this effect in comparison to other languages. From this article, you will learn how the default method parameters work in Java.

Advertisement

1. Java default parameters in practice

The syntax of Java language doesn’t allow you to declare a method with a predefined value for a parameter. Fortunately, you can achieve the same effect with simple code constructions.

There are several options that you may use to simulate behavior known from other programming languages. You can:

  • use method overloading
  • allow nulls as an input
  • declare a method with Java Varargs

Let’s take a closer look at these options.

1.1. Java default parameters with method overloading

Probably the best option to achieve default method parameters in Java is by using the method overloading. Method overloading allows you to declare several methods with the same name but with a different number of parameters.

How to use method overloading to simulate default method parameters?

By calling a more complex method by a simpler one.

Here is a practical example of a method which allows you to query for an optional number of some documents:

List<Document> search(String query) {
   return search(query, 10, 0);
}

List<Document> search(String query, Integer limit, Integer offset) {
   // method implementation
}

The only required parameter is a query string. As you can see, you only have to implement the method with the highest number of parameters. To clarify, the simple method is just a proxy that passes its parameter to the more complex method and provides default parameter values for the optional arguments.

In comparison to other options, the main advantage of method overloading is the simplicity for the client code. You can easily read what set of parameters is allowed for a given method.

Although method overloading is strongly recommended, it’s worth knowing about other possibilities.

1.2. Allowing Nulls as method parameters

Another option is to declare a single method that accepts all possible parameters. Next, in the body of the method, you can check which parameters are nulls and assign them default values.

In this approach, our previous example looks as follows:

List<Result> search(String query, Integer limit, Integer offset) {
   if (limit == null) {
       limit = 10;
   }
   if (offset == null) {
       offset = 0;
   }
   // method implementation
}

There are two main disadvantages to this approach. First, you still need to pass all arguments in client code. Even if some of them are nulls. Second, you need to know which parameters are nullable as you can’t tell that just by looking at the method declaration.

What is more, many developers consider reassinging method parameters as bad practice as it makes the code harder to follow. With this in mind, many static code analysis tools allow you to check for this kind of code smell.


Some people suggest wrapping parameters which aren’t required inside Java 8 Optional class. However, the Optional type was designed for method outputs and not inputs. If you are interested why, check out my other article about Java Optional use cases.

1.3. Varargs parameter

The Varargs option is limited only to arguments of the same type and meaning. Therefore, it doesn’t actually solve the problem of default parameters in Java methods. But you may consider it in some cases.

User createUser(String login, Right... rights) {
    rights = User.DEFAULT_RIGHTS;  
    // implementation
}

Technically, it’s even possible to use Varargs as a single optional parameter. In this case, you don’t have to pass null in the client code to use the default value. Yet, it rather feels like an awful hack. I recommend sticking to method overloading.

2. Java default parameters in long parameter list

The main problem with method overloading as a solution for default parameter values reveals itself when a method accepts multiple parameters. Creating an overloaded method for each possible combination of parameters might be cumbersome.

To deal with this issue, you should introduce the Parameter Object pattern.

What is it?

Simply put, the Parameter Object is a wrapper object for all parameters of a method.

But wait! Aren’t we just moving the problem of the long parameter list from a method to the constructor of the new class?

Indead, we are. But class constructors give us one additional solution for the problem which is the Builder pattern.

2.1. Solving Java default parameters with Parameter Object

As mentioned before, the first thing you need is a parameter object class that wraps the list of method parameters. Let’s see how it can look like for a method from the previous example:

class SearchParams {

   private static final int DEFAULT_LIMIT = 10;
   private static final int DEFAULT_OFFSET= 0;

   private String query;
   private int limit = SearchParams.DEFAULT_LIMIT;
   private int offset = SearchParams.DEFAULT_OFFSET;

   // getters

   }

}

As you can see, the implemented parameter object is nothing more than just a regular POJO. The advantage of the Parameter Object over a regular method parameter list is the fact that class fields can have default values. Just like in the above example.

That’s it. Now you have all default parameters in a single place.

2.2. … and  Builder patterns

Once you create a wrapper class for the method parameter list you should also create a corresponding builder class. Usually, you’ll do it as an inner static class. 

But don’t type builders alone, automate this work! 

Popular Java IDEs provide plugins that generate builder classes.

In our example the builder will look as follows:

class SearchParams {

   // getters ...

   private SearchParams(Builder builder) {
       query = builder.query;
       limit = builder.limit;
       offset = builder.offset;
   }

   public static Builder newBuilder() {
       return new Builder();
   }

   public static final class Builder {

       private String query;
       private int limit;
       private int offset;

       private Builder() {
       }

       public Builder withQuery(String val) {
           query = val;
           return this;
       }

       public Builder withLimit(int val) {
           limit = val;
           return this;
       }

       public Builder withOffset(int val) {
           offset = val;
           return this;
       }

       public SearchParams build() {
           return new SearchParams(this);
       }

   }

}

The final step is to use the builder to construct a new parameter object. In this case, you assign only selected parameters. For those parameters you skip, their default values are going to be used. Here’s an example:

SearchParams params = SearchParams.newBuilder()
       .withQuery("gold")
       .withOffset(20)
       .build();
// params.limit = 10 by default

Our example is really simple as the method has only three parameters so it might look like overengineering. In fact, the solution for default parameters using Parameter Object and Builder shines when the list of method parameters is much longer.

Construction site

Conclusion

Let’s sum up. 

Java doesn’t have a simple solution for default method parameters as available in other common programming languages. Yet, you can simulate it using other Java constructions and patterns. In addition, you learn a simple approach with method overloading which works for methods with a short parameter list. For complex methods, the Parameter Object pattern is more flexible.

If you find the article useful, please share it with your friends. Don’t forget to subscribe so I can notify you about other similar posts.

Facebooktwittergoogle_plusredditlinkedinmail
Advertisement