D3 - Optional<T>, Enums, Supplier.

Software, Java

Optional

You know how in java you must state the returned type of each function, in it's signature? Optional grants you some versatility. It allows dealing with null cases explicitly and clearly. Example: Let's say we write a function that should return a String, but it won't always return one - in this case we can state the return type as Optional.

public static Optional<String> func(String s) {
    String str = Optional.ofNullable(s).orElse("Default text, s was null");
    return str;

Later in the function we can use methods of Optional like .ofNullable which sets a value to the Optional object, and allow it to be null. We can later check it's value without getting NullPointerException. Another useful method is .orElse which sets the value of the Optional object to something in case it is null. Both of these are examples of compact, readable ways to replace multiple If conditions, and risk of running into exceptions. Optional has many more useful methods.

Enumerate

Enum is a kind of class which allows us to restrict it's possible instances. Right after the enum class signature, we state the possible instaces and constructor arguments, the only thing the user who generate an instance is allowed to do - is to choose which of the instances we constructed to initiate. A small example might be clearer than explaination:

public enum Season {
    WINTER("Wind goes brrr"),
    SUMMER("It's over 9,000 degrees"),
    SPRING("Aahh, the great outdoors"),
    FALL("Crispy leaves everywhere!");

    private final String weatherVibes;

    private Season(String s) {
        this.weatherVibes = s;
    }
    private void printWhatIsUp(){
        System.out.println(weatherVibes);
    }
}

Each of the possible instances(Winter, Summer, etc.) calls the constructor with the String it has as an argument. When the function printWhatIsUp is called, it will print the matching sentence for the specific instance. For say:

Season currentSeason = Season.FALL;
currentSeason.printWhatIsUp();

Output:

Crispy leaves everywhere!

Supplier

Supplier is java's version of generators. It is an interface that has one function get() that returns a value. Once implemented right and used in a stream, it will generate new values as much as requested. Example:

public class HowHungryRU implements Supplier<String> {
    private int amount = 1;
    @Override
    public String get() {
        return String.format("I could eat %d burgers!", ++amount);
    }
}

Stream<String> s = Stream.generate(new HowHungryRU());
s.limit(3).forEach(System.out::println);

OutPut:

I could eat 2 burger!
I could eat 3 burger!
I could eat 4 burger!

Up here, the stream prints the string generated each time as requested by forEach from HowHungryRU. Each time amount is increased by 1, and thus, the hungry dude (let's say there is one) gets hungrier and hungrier until he claims to be able to eat 4 burgers! Sombody better feed him...

Note that we used stream.limit() which limited the number of generations from HowHungryRU to a maximum of 3. We don't want the dude to have a abdominal pains...

RwK