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
🌐
Reddit
reddit.com › r/java › opinions on using optional as parameter
r/java on Reddit: Opinions on using Optional<> as parameter
January 23, 2022 -

I like using Optional<> to return values that may be null but today I saw people using them to accept parameters that may be null, if the parameter wasn't an Optional<> then it couldn't be null. I personally don't like doing that but I'd like to hear some opinions.

They were doing things like

double getStartingBalance(@NotNull Optional<UUID> user) { ... }

In my opinion, Optional<> is used to force the developer to handle null values. If my method is called and may return null, I'll return an Optional<> to make sure that null is handled but if I design the method and define that something cannot be null I can just use Objects#requereNonNull or if it can be null a simple check does the job. Also having to box values in optionals and having to use Optional.empty() for nulls to call a method is messy and makes the call harder to read.

So what are your opinions on using optionals as parameters?

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);
}
🌐
Stackify
stackify.com › optional-parameters-java
Optional Parameters in Java: Strategies and Approaches-Stackify
April 10, 2024 - 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 ill-advised strategy of allowing callers to supply null values.
🌐
FavTutor
favtutor.com › blogs › java-optional-parameters
Optional Parameters in Java Explained (with code)
August 23, 2023 - Optional Parameters mean even if a user is not providing the arguments, the function will get executed without any error. In the following sections, we will discuss multiple ways to implement optional parameters in java.
🌐
Rosetta Code
rosettacode.org › wiki › Optional_parameters
Optional parameters - Rosetta Code
2 weeks ago - Java has no optional parameters, but methods can be overloaded on the number and types of arguments, which can be used to effectively achieve optional positional parameters.
🌐
Baeldung
baeldung.com › home › java › core java › optional as a record parameter in java
Optional as a Record Parameter in Java | Baeldung
January 16, 2024 - And getting the exception is sometimes used to identify the absence of value. The main goal of Optional is to represent a method return value that represents the absence of a value.
🌐
DZone
dzone.com › articles › optional-method-parameters
Optional Method Parameters
February 28, 2017 - Would that stop you from using Java? Obviously not. Ah, us clean coders! Such a good movement, but sometimes we tend to overdo things. But yes, that could be a code smell, especially if that one thing would be the conditional logic we talked about earlier. I’m not so sure if it would be so evil if the logic looked like this: public void myMethod(Optional<String> optionalArgument) { // some code String argument = optionalArgument.orElse("reasonable default"); doSomething(argument); // some code }
Find elsewhere
🌐
JetBrains
jetbrains.com › help › inspectopedia › OptionalUsedAsFieldOrParameterType.html
'Optional' used as field or parameter type | Inspectopedia Documentation
March 31, 2026 - Using a field with the java.util.Optional type is also problematic if the class needs to be Serializable, as java.util.Optional is not serializable. ... class MyClass { Optional<String> name; // Optional field // Optional parameter void setName(Optional<String> name) { this.name = name; } }
🌐
GitConnected
levelup.gitconnected.com › an-argument-for-using-optional-as-input-parameters-43b13fe6dfce
An argument for using Optional as input parameters | by Petre Popescu | Level Up Coding
December 23, 2022 - There is an ongoing debate in the Java community regarding Optional and if it should be used as input parameters for methods or only as return values. Most people, including big names from the Java ecosystem, advocate for using Optional only as output. Even [Sonar has a rule](https://rules.sonarsource.com/java/RSPEC-3553) that grants a “Major” severity for Optional as parameter.
🌐
Java Code Geeks
javacodegeeks.com › home › core java
Java optional parameters - Java Code Geeks
November 23, 2018 - Brian Goetz, who is Java language architect at Oracle once stated that Optional was added to the standard library with methods’ results in mind, not their inputs. But software developers are rebels and don’t like listening to authorities. This argument may also seems weak. We have to go deeper. ... The parameter can be either a wrapped value or the empty optional instance.
🌐
W3Schools
w3schools.com › java › java_methods_param.asp
Java Method Parameters
Java Examples Java Videos Java Compiler Java Exercises Java Quiz Java Code Challenges Java Practice Problems Java Server Java Syllabus Java Study Plan Java Interview Q&A ... Information can be passed to methods as a parameter.
🌐
ThisCodeWorks
thiscodeworks.com › optional-parameters-in-java-4-different-methods-with-code › 63bba52b89ee9c001559a9cf
Optional Parameters in Java: 4 Different Methods (with code) | thiscodeWorks
In this article, we will learn about the optional parameters in java and implementation using different methods with syntax and example: https://favtutor.com/blogs/java-optional-parameters
🌐
GitHub
github.com › Auties00 › NamedParameters
GitHub - Auties00/NamedParameters: Named and Optional parameters for Java 17 · GitHub
If you want to make a parameter optional, you can do so by applying the @Option annotation:
Starred by 44 users
Forked by 4 users
Languages   Java
🌐
Xperti
xperti.io › home › optional parameters in java: common strategies and approaches
Java Optional Parameters Approach In Code Practice
March 12, 2026 - When a method is written in Java code, all the required parameters are listed. In certain situations, the developer may not know the exact number of arguments that will be provided to this function at the time of declaring it. In such a case, Java optional parameter allow additional parameters that were initially not defined.
🌐
Oracle
docs.oracle.com › javase › 8 › docs › api › java › util › Optional.html
Optional (Java Platform SE 8 )
April 21, 2026 - If a value is present the result must include its string representation in the result. Empty and present Optionals must be unambiguously differentiable. ... Java™ Platform Standard Ed.
🌐
Medium
medium.com › @bubu.tripathy › clean-code-optional-parameters-327d67abbf90
Clean Code: Optional Parameters. When dealing with optional parameters… | by Bubu Tripathy | Medium
February 26, 2024 - ⭐️ If you’re using Java 8 or later, you can leverage default parameter values in interfaces to provide default values for optional parameters.
Top answer
1 of 4
5

Whether something is "OK to use" depends on intent, team coding practices, common programming idioms, and how strictly you want to adhere to API guidelines.

First, the facts about Optional<T>:

A container object which may or may not contain a non-null value.

...

API Note:

Optional is primarily intended for use as a method return type where there is a clear need to represent "no result," and where using null is likely to cause errors. A variable whose type is Optional should never itself be null; it should always point to an Optional instance.

Source: Oracle Java 11 JDK documentation (emphasis, mine)

Not a lot of concrete guidance here beyond the recommendation that Optional<T> be used as a return type. In a strict sense, you are not using this as a return type, therefore the answer is "no, this is not OK." On the other hand, you are using it as the type for a field which may contain null. So you seem to satisfy the first part.

But it works.

That's why it's important to remember these are guidelines. The mechanics of whether you can use something are a different discussion, and hence, your question. Instead, I like to see how these optional fields are being used to ensure a more suitable OO design doesn't already exist.

If I had to look at a codebase that was peppered with field.ifPresent(foo -> foo.method()) every time field was used, I would start to wonder if we have a design problem with field rather than it's type. Even in cases where you have field.isPresentOrElse(foo -> foo.method(), () -> something else), I still think we are missing something. Frankly, the constant calls to the Optional<T> methods as a round-about way to avoid NullPointerExceptions makes me think the Null Object Pattern might be a better choice here. Every method in the "null object" can be a no-op. Getters can return pre-canned values (whatever the "or else" part of Optional.ifPresentOrElse() would have returned).

I don' like optional dependencies because they can be null, so now I need to incessantly check for null, or I need to use some other non-idiomatic construct like Optional<T> with a bunch of pass-through method calls in lieu of null-checks.

Code is much cleaner if you can simply call field.method() rather than field.ifPresent(foo -> foo.method()).

Some additional notes:

  • The guidance in this answer applies best to situations where the T is a complex type. When T is a string, boolean, or numeric type, then the "optional" part of an Optional<T> becomes meaningful. An Optional<boolean> can be true, false, or not present, which your application could interpret as "not specified." In that case, document this fact on the field.

    • In the case of a String, consider defaulting to an empty string instead. No need for null if you have proper encapsulation. A constructor or setter can enforce the "empty string instead of null" constraint.
  • When T is a complex type, consider other, more straight-forward designs first before resorting to an Optional<T>, if for no other reason than the Principle of Least Astonishment.

  • Choose code that is easy to read first. In situations like this, I like to write the same code multiple ways. Consider writing it when checking for nulls, using another more suitable design pattern (like Null Object Pattern), and using an optional. Same code. 3 different styles. Which one do you like?

    • And then present the same 3 styles to a colleague to see which one they like.

In the end, you get working code either way. Personal taste, other object-oriented design practices and team habits play a bigger role in this decision than API guidance.

2 of 4
5

Optional is now intended to be used as a Monad. Java designers effectively admitted that by adding Optional.stream() method.

Ignore earlier discussions about:

  • serialization. Serialization should not be used in new code
  • library interfaces. They are not different from your own.
  • method argument. Using Optional as argument in much more idiomatic than doing a conditional dispatch over method overloads.

Surprisingly, important reasons not to use an Optional as a field are:

  • memory consumption - it increases the size of your field up to 4 times.
  • performance - it introduces additional memory indirection

These are only applicable to long-lived numerous objects (example: gamedev).