1

I have a class like so

class User {
  private String firstName;
  private String lastName;

  ...
}

I want the lastName property to be optional. How do I accomplish this in Java?

In some languages it's quite elegant and simple wherein we just append a question mark after the field name.

Zabuzard
  • 25,064
  • 8
  • 58
  • 82
jhon.smith
  • 1,963
  • 6
  • 30
  • 56
  • 5
    There is no concept for this in Java. Most people would just assign `null` to it and return `Optional` on methods that would return it. (It is usually not recommended to store the thing as `Optional`, nor to take such arguments, only to return it). – Zabuzard Nov 22 '21 at 12:34
  • 6
    You've already achieved it. All reference types are nullable. – Sotirios Delimanolis Nov 22 '21 at 12:34
  • 1
    What do you mean by optional ? It's already kind of optional since you decide if you assign a value to your attribute or not. – vincrichaud Nov 22 '21 at 12:37
  • 1
    In languages like Kotlin, a `String` is non-nullable whereas a `String?` is nullable. In Java, all Strings are nullable and therefore you can treat all Strings as optional. Now your question should be: how to make them non-optional. That's a tricky one. – k314159 Nov 22 '21 at 12:38

4 Answers4

4

Overview

There is no language concept for this in Java.

In Java, all (non-primitive) types are nullable, hence can be seen optional. So you could just assign it null and call it a day.

To overcome the problems related with that, make intention clearer and strive for fail-fast, what I have seen being used a lot would be to assign null to it internally and return Optional<String> on methods that would return it, such as a getLastName() method.


Code example

So one way doing this could be:

class User {
  private String firstName;
  private String lastName;

  User(@NotNull String firstName) {
     this(firstName, null);
  }

  User(@NotNull String firstName, @Nullable String lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  @NotNull Optional<String> getLastName() {
    return Optional.ofNullable(lastName);
  }

  void setLastName(@Nullable String lastName) {
    this.lastName = lastName;
  }

  ...
}

I used the @NotNull and @Nullable annotations intentionally to make it clearer for you where null could be allowed in such a design.

Note that if you have more optional parameters, a builder-pattern might also become handy.

Ultimately, also think about whether having optional values is a good design in the first place - maybe you can redesign the entire thing on a bigger picture to aovid the situation all together.


Optional as field or argument

Note that it is usually not recommended to store the field as Optional<String>, nor to take such arguments, for example a setLastName(Optional<String>).

Optional was designed only to be used by methods wo want to indicate the lack of a return value.

You can read more about that here:

Zabuzard
  • 25,064
  • 8
  • 58
  • 82
1

Just assign null to it, when you call it. you can also just assign it a empty string and then if needed for your use case have a method that checks if it is empty and from there knows that that particular user only has a first name user("John","")

Tp323
  • 29
  • 11
1

You could use the Optional monad. Though honestly, I'd just keep the values as-is, and treat the fact that they are nullable elsewhere (depends on the case):

Optional.ofNullable(user.getFirstName()).orElse("unknown");

Optional.ofNullable(user.getFirstName()).orElseThrow(() 
    -> new InvalidArgumentException("First name is required);
Peter Walser
  • 15,208
  • 4
  • 51
  • 78
1

Maybe just create a getter that returns Optional:

class User {
  private String firstName;
  private String lastName;

  public String getFirstName() {
    return firstName;
  }

  public Optional<String> getLastName() {
    return Optional.ofNullable(lastName);
  }
}

and then:

User user = new User();
...
String lastName = user.getFirstName();
Optional<String> lastName = user.getLastName();
Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140