Java Optional <T> question, am I doing this right?
I had a "bad habit" of throwing null
at places like enumerators when something doesn't exist.
Example:
private enum Foo {
NULL(1, null, 2),
NOT_NULL(3, new Bar(), 4);
private int a, c;
private Bar b;
Foo(int a, Bar b, int c) {
this.a = a;
this.b = b;
this.c = c;
}
}
So now I'm trying to convert my code to use Optional<T>
As everyone suggests, but I'm not sure if I'm doing it right.
Here's my code (Trimmed enum):
public static enum Difficulty {
EASY, MEDIUM, HARD
}
public static enum SlayerTasks {
NONE(0, Optional.empty(), Optional.empty(), Optional.empty()),
NPC(1, Optional.of(Difficulty.EASY), Optional.of("That one place."), Optional.of(1));
private int taskId;
private Optional<Difficulty> difficulty;
private Optional<String> location;
private Optional<Integer> npcId;
SlayerTasks(int taskId, Optional<Difficulty> difficulty, Optional<String> location, Optional<Integer> npcId) {
this.taskId = taskId;
this.difficulty = difficulty;
this.location = location;
this.npcId = npcId;
}
public int getTaskId() {
return taskId;
}
public Difficulty getDifficulty() {
return difficulty.get();
}
public String getLocation() {
return location.get();
}
public int getNpcId() {
return npcId.get();
}
}
What worries me is the documentation related to #get()
found here where it states:
If a value is present in this Optional, it returns a value, otherwise a NoSuchElementException is thrown.
So, I figured that to prevent this, I would wrap the getter in #isPresent()
, but then I couldn't figure out how to return empty.
Is this the correct way to do something, or am I missing something? I am not looking for "Fix", I am looking for information on efficiency and good practice.
source to share
You need to ask yourself what you want your getter to do if nothing is returned.
There are only four options:
- Returns zero (but then you are back to what you were trying to avoid);
- Let your recipient return
Optional<T>
insteadT
; - Returns the default value if nothing is set;
- Throw an exception.
I would go with 2 if it wasn't for a very clear correct answer to what should be the default. 4 is only suitable if the client code always needs to know if there is something in there and only ask it if there is (which would be unusual, though not impossible).
source to share
IMO, if you are implementing your logic with a "maybe" monad (optional values), you should stick with the optional object and cast it, fetching the wrapped value only if necessary.
To change the invalid value, you can use methods Optional.ifPresent()
, Optional.map()
or Optional.flatMap()
for example
Optional<Difficulty> difficulty = NPC.getDifficulty();
difficulty.ifPresent(diff -> { /* do comething here ... */ });
source to share