Let me show you guys this code:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
String audioSystemVersion = "UNKNOWN"; | |
if (myCar != null) { | |
AudioSystem audioSystem = myCar.getAudioSystem(); | |
if (audioSystem != null) { // the card has audio system. | |
audioSystemVersion = audioSystem.getVersion(); | |
} | |
} |
To give some historical context, Tony Hoare - one of the giants of computer science - wrote, "I call it my billion-dollar mistake. It was the invention of the null reference in 1965. I couldn't resist the temptation to put in a null reference, simple because it was so easy to implement."
What can you do to prevent unintended null pointer exceptions ? You can be defensive and add checks to prevent null references like you see in the above code, or you can use one of the amazing stuffs of Java 8 like the Optional pattern. We are going directly to the action, let me show you some code!
- Creating Optional objects
An empty Optional.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOptional<AudioSystem> sc = Optional.empty();
A non null Optional. If audioSystem were null, a NullPointerException would be thrown. Take it into account.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersAudioSystem audioSystem = new AudioSystem(); Optional<AudioSystem> as = Optional.of(audioSystem);
Finally, you can create an Optional from a null reference. If audioSystem were null, the resulting Optional would be an empty Optional.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOptional<AudioSystem> as = Optional.ofNullable(audioSystem); - Do something if value present
Instead of this
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersAudioSystem as = ....; if (as != null) { Sysmte.out.println(as); }
better this (functional style).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOptional<AudioSystem> as = ...; as.ifPresent(System.out::println);
or you can use it the imperative way (not recommended)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOptional<AudioSystem> audioSystem = ...; if(audioSystem.isPresent()){ System.out.println(audioSystem.get()); } - Filter values using filter method
Instead of this
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersAudioSystem as = ...; if(as != null && "Pionner".equals(as.getBrand())){ System.out.println(as); }
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOptional<AudioSystem> maybeAudioSystem = ...; maybeAudioSystem.filter(as -> "Pionner".equals(as.getBrand()) .ifPresent(as -> System.out.println(as)); - Extracting and transforming values using the map method
Instead of this
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersif(car != null){ AudioSystem as = car.getAudioSystem(); if(as != null && "Pionner".equals(as.getBrand()){ System.out.println("ok"); } }
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersmaybeCar.map(Car::getAudioSystem) .filter(as -> "Pionner".equals(as.getBrand()) .ifPresent(() -> System.out.println("ok"));
The purpose of Optional is not to replace every single null reference in your codebase but rather to help design better APIs in which—just by reading the signature of a method—users can tell whether to expect an optional value. In addition, Optional forces you to actively unwrap an Optional to deal with the absence of a value; as a result, you protect your code against unintended null pointer exceptions.
Killing the nulls!
This comment has been removed by the author.
ReplyDeleteThank you for your feedback ;)
ReplyDelete