There are several ways to simulate optional parameters in Java.

Method overloading

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

Varargs

a) All optional parameters are of the same type:

Copyvoid 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:

Copyvoid 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 the different meaning you need some way to distinguish them.

Nulls

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

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

Optional class

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

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

Update: Java 8 includes the class java.util.Optional out-of-the-box, so there is no need to use guava for this particular reason in Java 8. The method name is a bit different though.

Builder pattern

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

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

Maps

When the number of parameters is too large and for most of the default values are usually used, you can pass method arguments as a map of their names/values:

Copyvoid foo(Map<String, Object> parameters) {
    String a = ""; 
    Integer b = 0;
    if (parameters.containsKey("a")) { 
        if (!(parameters.get("a") instanceof Integer)) { 
            throw new IllegalArgumentException("...");
        }
        a = (Integer)parameters.get("a");
    }
    if (parameters.containsKey("b")) { 
        //... 
    }
    //...
}

foo(ImmutableMap.<String, Object>of(
    "a", "a",
    "b", 2, 
    "d", "value")); 

In Java 9, this approach became easier:

Copy@SuppressWarnings("unchecked")
static <T> T getParm(Map<String, Object> map, String key, T defaultValue) {
  return (map.containsKey(key)) ? (T) map.get(key) : defaultValue;
}

void foo(Map<String, Object> parameters) {
  String a = getParm(parameters, "a", "");
  int b = getParm(parameters, "b", 0);
  // d = ...
}

foo(Map.of("a","a",  "b",2,  "d","value"));

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

Answer from Vitalii Fedorenko on Stack Overflow
Top answer
1 of 16
1975

There are several ways to simulate optional parameters in Java.

Method overloading

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

Varargs

a) All optional parameters are of the same type:

Copyvoid 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:

Copyvoid 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 the different meaning you need some way to distinguish them.

Nulls

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

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

Optional class

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

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

Update: Java 8 includes the class java.util.Optional out-of-the-box, so there is no need to use guava for this particular reason in Java 8. The method name is a bit different though.

Builder pattern

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

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

Maps

When the number of parameters is too large and for most of the default values are usually used, you can pass method arguments as a map of their names/values:

Copyvoid foo(Map<String, Object> parameters) {
    String a = ""; 
    Integer b = 0;
    if (parameters.containsKey("a")) { 
        if (!(parameters.get("a") instanceof Integer)) { 
            throw new IllegalArgumentException("...");
        }
        a = (Integer)parameters.get("a");
    }
    if (parameters.containsKey("b")) { 
        //... 
    }
    //...
}

foo(ImmutableMap.<String, Object>of(
    "a", "a",
    "b", 2, 
    "d", "value")); 

In Java 9, this approach became easier:

Copy@SuppressWarnings("unchecked")
static <T> T getParm(Map<String, Object> map, String key, T defaultValue) {
  return (map.containsKey(key)) ? (T) map.get(key) : defaultValue;
}

void foo(Map<String, Object> parameters) {
  String a = getParm(parameters, "a", "");
  int b = getParm(parameters, "b", 0);
  // d = ...
}

foo(Map.of("a","a",  "b",2,  "d","value"));

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

2 of 16
595

varargs could do that (in a way). Other than that, all variables in the declaration of the method must be supplied. If you want a variable to be optional, you can overload the method using a signature which doesn't require the parameter.

Copyprivate boolean defaultOptionalFlagValue = true;

public void doSomething(boolean optionalFlag) {
    ...
}

public void doSomething() {
    doSomething(defaultOptionalFlagValue);
}
🌐
Javadoc.io
javadoc.io › doc › com.landawn › abacus-util-jdk7 › 1.2.8 › com › landawn › abacus › util › OptionalBoolean.html
OptionalBoolean (abacus API Documentation)
package-list path (used for javadoc generation -link option) https://javadoc.io/doc/com.landawn/abacus-util-jdk7/1.2.8/package-list ·
🌐
Baeldung
baeldung.com › home › java › core java › guide to java optional
Guide To Java Optional | Baeldung
February 15, 2026 - In the above example, we use only two lines of code to replace the five that worked in the first example: one line to wrap the object into an Optional object and the next to perform implicit validation as well as execute the code. The orElse() method is used to retrieve the value wrapped inside an Optional instance. It takes one parameter, which acts as a default value.
🌐
FavTutor
favtutor.com › blogs › java-optional-parameters
Optional Parameters in Java Explained (with code)
August 23, 2023 - Find out what are optional parameters in java and how to declare and implement them. We also included syntax and examples for each method.
🌐
Sonar Community
community.sonarsource.com › rules and languages › report false-positive / false-negative...
Rule java:S6814 "Optional REST parameters should have an object type" false positive - Report False-positive / False-negative... - Sonar Community
May 16, 2024 - Java Which rule? java:S6814 Optional ... boolean parameters. For example following seems to work: @RequestParam(value = "test", required = false) final boolean ......
🌐
Oracle
docs.oracle.com › javase › 8 › docs › api › java › util › Optional.html
Optional (Java Platform SE 8 )
April 21, 2026 - This method supports post-processing on optional values, without the need to explicitly check for a return status. For example, the following code traverses a stream of file names, selects one that has not yet been processed, and then opens that file, returning an Optional<FileInputStream>:
🌐
GoLinuxCloud
golinuxcloud.com › home › java › crafting perfect code with java optional parameters
Crafting Perfect Code with Java Optional Parameters | GoLinuxCloud
October 7, 2023 - Let us now take a practical example of creating patterns to have optional java parameters. First, we will create a public static nested class inside our Main class. StudentBuilder is our builder class. Then we will define all the fields of the outer class of the StudentBuilder.
Find elsewhere
Top answer
1 of 5
6

I agree that you should go with what makes more sense semantically, but I also find that, when the boolean argument is optional, the thing that fairly often makes more sense when omitting it is for it to have a default value of false - in languages that initialize instances of primitive types, false is generally the default value for a boolean.

It then acts as an "on" flag for the less commonly used feature. So that you have:

DoSomething(someParams);
DoSomething(someParams, true);

// Or, if your language supports named parameters
DoSomething(someParams, optionalFeature: true);

So, I would have a slight bias for the parameter to default to false, unless doing so feels unnatural (as in, it feels unnatural as a sentence when you read it). Sometimes, the exceptional behavior is better conceptualized as turning something off (for example, setters that take a boolean argument are often constructed this way, see Joop Eggen's answer; however, you should strive for encapsulation, and minimize the use of getters and setters).

If the feature controlled by the boolean argument is not less commonly used (in the general case), I wouldn't make it optional. Design for the general case. If there's a small number of users with applications that mostly use one value for the argument, they can create their own wrapper.

As for the logic inside the method, if it turns out that your choice makes it awkward to write conditionals, just introduce a new well-named variable with the flipped value (or a new variable that summarizes several boolean checks that repeat, or whatever) - it's not going to be a problem if your method is fairly short (which it should be - you shouldn't have a sprawling tree of nested if-statements in there).

2 of 5
10

In line with @Ewan's arguments, choose the one making the code easier to read and reason about.

For example, double negations (!isNotA or Ewan's !FileDoesntExist) are the kind of conditional statements you want to avoid because they cause a cognitive burden. Unbearable when flag names are meaningless.

Negation involves an extra cognitive step (even when the negation is in the name of the flag). We usually think first in the is part and then negate it. So, the more your if blocks look like the following, the better

//only for illustration
if(isA && isB)
else (isA)     //isA && !isB
else (isB)     //!isA && isB
else           //!isA && !isB

Ok, this is easier to say than done, but think about it. It depends on how we translate (mentally) rules into conditions. If we think in terms of "is not", we will end up with flags prefixed with isNot, and it's ok if we can address it later. For instance, we can invert the flag isA = !isNotA and use isA instead. 1

To summarize, use the notation that makes your code easier to read (to me, affirmative statements), always use meaningful names and avoid negations and double negations as the plague; your teammates will appreciate it.


1: Do it only to make your conditionals easier to read and reason about. Don't systematically invert flags all over the code.

🌐
Java Code Geeks
examples.javacodegeeks.com › home › java development › core java
Java Optional Parameters - Java Code Geeks
August 11, 2021 - In this article, we’ve looked at a variety of strategies for working with optional parameters in Java, such as method overloading, the builder pattern, and the strategy of allowing callers to supply null values. We highlighted the relative strengths and weaknesses of each strategy and provided usage for each. Java Array – java.util.Arrays Example (with Video)
🌐
Baeldung
baeldung.com › home › java › core java › java default parameters using method overloading
Java Default Parameters Using Method Overloading | Baeldung
January 8, 2024 - The other optional parameters are milk (in ml), herbs (to add or not to add), and sugar (in tbsp). If any of their values are not provided, we assume the user doesn’t want them.
🌐
Medium
medium.com › @hopewellmutanda › java-8-optional-usage-and-best-practices-975c41d66822
Java 8 Optional Usage and Best Practices | by Hopewell Mutanda | Medium
May 28, 2019 - If you do need to serialize an object that contains an Optional value, the Jackson library provides support for treating Optionals as ordinary objects. What this means is that Jackson treats empty objects as null and objects with a value as fields containing that value. This functionality can be found in the jackson-modules-java8 project. b) Do not use it as a parameter for constructors and methods as it would lead to unnecessarily complicated code.
🌐
GitHub
github.com › remkop › picocli › issues › 1108
support Optional<> for better tri-state boolean · Issue #1108 · remkop/picocli
June 12, 2020 - support Optional<> for better tri-state boolean#1108 · Copy link · Labels · theme: parserAn issue or change related to the parserAn issue or change related to the parsertype: enhancement ✨ · Milestone · 4.6 · maxandersen · opened · on Jun 12, 2020 · Issue body actions · currently when you do: @Option(names={"--cds"}, description = "If specified Class Data Sharing (CDS) will be used for building and running (requires Java 13+)", negatable = true) Optional<Boolean> cds = Optional.empty(); you get: Only boolean options can be negatable, but field java.util.Optional<Boolean> dk.xam.jba
Author   remkop
🌐
Oracle
docs.oracle.com › en › java › javase › 21 › docs › api › java.base › java › lang › Boolean.html
Boolean (Java SE 21 & JDK 21)
January 20, 2026 - Compares this Boolean instance with another. ... Returns an Optional containing the nominal descriptor for this instance.
🌐
Oracle
docs.oracle.com › en › java › javase › 11 › docs › api › java.base › java › util › Optional.html
Optional (Java SE 11 & JDK 11 )
January 20, 2026 - Parameters: exceptionSupplier - ... - if no value is present and the exception supplying function is null · X extends Throwable · public boolean equals​(Object obj) Indicates whether some other object is "equal to" this Optional....
🌐
DEV Community
dev.to › lexlohr › optional-booleans-p0d
Optional booleans? - DEV Community
January 16, 2020 - If something can have three states, it shouldn't be a boolean. If it needs to have one of two states, then existing data should be updated with the default (whether that's true or false). "Optional booleans" only really pop up when boolean has been added to a schema, but the developers haven't made it required because they don't want to break backwards-compatibility.
🌐
Delft Stack
delftstack.com › home › howto › java › java optional parameter
Java Optional Parameters | Delft Stack
October 12, 2023 - Thus it takes default values for optional parameters. The build() method constructs the User object and returns it. public class TestUser { public static void main(String args[]) { User user1 = new User.UserBuilder("John", "Doe").age(24).email("john.doe@dex.com").build(); System.out.println(user1); User user2 = new User.UserBuilder("Jack", "Luther").build(); System.out.println(user2); } } ... In Java, Varargs (variable-length arguments) allows the method to accept zero or multiple arguments.