Sentenced to empty the disaster
As a brick remover, we must be all too familiar with nullPointerexceptions. Don’t tell me you rarely nullPointerExceptions unless you like them.
But for many apes, NullPointerException is also the closest member of the Exception family.
To avoid nullPointerExceptions coming to us, we often do the following.
if (data ! = null) { do sth. }Copy the code
If you use an object more than once in a class, you might want to do something about it, so:
The “ninth Wonder of the World” was born. Maybe you will think, you are not the only one in the project who will do this, then press Command+Shift+F and you will see the truth:
What, we have close to 10,000 lines of code that are nulling?
All right, now, let’s get down to business.
NullObject mode
We call it a “void disaster” for the numerous nullifies in the project, which have a very bad impact on code quality and cleanliness.
So, how does this work? You’ve probably heard of NullObject, but it’s not our weapon of the day, but NullObject is something to talk about.
What is NullObject mode?
In object-oriented computer programming, a null object is an object with no referenced value or with defined neutral (“null”) behavior. The null object design pattern describes the uses of such objects and their behavior (or lack thereof).
The above analysis is from Wikipedia.
The NullObject pattern was first published in the Programming Pattern Language series. In general, in object-oriented languages, null-checking is used to determine whether objects are empty before they are called, because the required method cannot be called on an empty reference.
A typical implementation of the empty object pattern is shown below (image from the network) :
Example code is as follows (named after the network, ha ha how lazy it is) :
Nullable is a Nullable interface used to determine whether an Object is Null or not. In Nullable mode, an Object is wrapped as a Null Object, which Nullable implements all methods of the original Object.
public interface Nullable {
boolean isNull(a);
}
Copy the code
This interface defines the behavior of the business object.
public interface DependencyBase extends Nullable {
void Operation(a);
}
Copy the code
This is the real class of the object, implementing the business action interface DependencyBase and the Nullable object action interface.
public class Dependency implements DependencyBase.Nullable {
@Override
public void Operation(a) {
System.out.print("Test!");
}
@Override
public boolean isNull(a) {
return false; }}Copy the code
This is an empty object, a null implementation of the behavior of the original object.
public class NullObject implements DependencyBase{
@Override
public void Operation(a) {
// do nothing
}
@Override
public boolean isNull(a) {
return true; }}Copy the code
When used, empty objects can be called through factory calls, or they can be called through other methods such as reflection (which usually takes a few more milliseconds) without going into detail here.
public class Factory {
public static DependencyBase get(Nullable dependencyBase){
if (dependencyBase == null) {return new NullObject();
}
return newDependency(); }}Copy the code
This is an example of how to use objects without NullPointerException. Instead of NullPointerException, we can use objects directly without worrying about NPE.
public class Client {
public void test(DependencyBase dependencyBase){ Factory.get(dependencyBase).Operation(); }}Copy the code
NullObject is a NullObject that can be used to NullObject objects. NullObject is a NullObject that can be used to NullObject objects. NullObject is a NullObject that can be NullObject objects. No more tedious work to define empty object interfaces and empty exclusive implementation classes.
.NR Null Object
NR Null Object is an Android Studio, IntelliJ IDEA, PhpStorm, WebStorm, PyCharm, RubyMine, AppCode, CLion, GoLand, DataGrip and other IDEA plugin Intellij. It can easily and quickly generate components required by its empty object mode according to existing objects. Its functions are as follows:
1. Analyze the methods that the selected class can declare as an interface; 2. Abstract the public interface; 3, create empty objects, automatically realize the public interface; 4. Nullable declaration for some functions; 5, can be added functions to generate again; Automatic function naming conventions
Let’s take a look at an example:
You can automatically Generate the corresponding Null Object component by selecting Generate and NR Null Object from the pop-up menu of the original Object that needs to be nulled several times.
So how do you get this plug-in?
installation
You can install it directly from the Plugins repository in the Preferences of the IDEA.
Select Preferences → Plugins → Browse Repositories
Search NR Null Oject or Null Oject for fuzzy query and click Install on the right to restart IDEA.
Optional
Alternatively, you can use Java8’s Optional option to execute a graceful short.
A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.
A container object that may or may not contain non-null values. If there is a value, isPresent () will return true and get () will return that value.
Without further ado, let me give you an example.
We have code like this, we need to get Info from Test2, but with the parameter Test4, we need to apply layer after layer, each layer can get an object that is empty, the final code looks like this.
public String testSimple(Test4 test) {
if (test == null) {
return "";
}
if (test.getTest3() == null) {
return "";
}
if (test.getTest3().getTest2() == null) {
return "";
}
if (test.getTest3().getTest2().getInfo() == null) {
return "";
}
return test.getTest3().getTest2().getInfo();
}
Copy the code
But with Optional, the whole thing is different.
public String testOptional(Test test) {
return Optional.ofNullable(test).flatMap(Test::getTest3)
.flatMap(Test3::getTest2)
.map(Test2::getInfo)
.orElse("");
}
Copy the code
Optional.ofNullable(test). If test is null, return a singleton empty Optional object. If test is not null, return an Optional wrapper object.
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
Copy the code
FlatMap (Test::getTest3) tests whether Test is null. If it is null, continue to return the singleton Optional object in step 1. Otherwise, call Test’s getTest3 method.
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if(! isPresent())return empty();
else {
returnObjects.requireNonNull(mapper.apply(value)); }}Copy the code
3. FlatMap (Test3::getTest2)
FlatMap (Test2::getInfo) is similar to flatMap, but flatMap requires Test3::getTest2 to return an Optional type. FlatMap does not require Test3::getTest2 to return an Optional type.
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if(! isPresent())return empty();
else {
returnOptional.ofNullable(mapper.apply(value)); }}Copy the code
5, orElse (” “); Gets the value in the map, if not empty, return value directly, if empty, return the passed parameter as the default value.
public T orElse(T other) {
returnvalue ! =null ? value : other;
}
Copy the code
If you look at this code, you may wonder whether it will become cleaner in a moment. Optional has its advantages for a long and complex short sentence. However, using Optional for simple short sentence also increases the reading cost of the code, the amount of code, and the learning cost of new members of the team. After all, Optional is not yet as popular as RxJava, and it has some limitations.
If you want to use Java8 Optional, ensure that android API level is 24 or higher.
You can also import Google’s Guava directly. (What is Guava? Tips from the authorities)
Guava is a set of core libraries that includes new collection types (such as multimap and multiset), immutable collections, a graph library, functional types, an in-memory cache, and APIs/utilities for concurrency, I/O, hashing, primitives, reflection, string processing, and much more!
A reference, like this:
Dependencies {the compile 'com. Google. Guava guava: 27.0 jre' / / or, for Android: API 'com. Google. Guava guava: 27.0 Android'}Copy the code
IDEA, however, is colored yellow by default, prompting you to migrate Guava expressions to the Java Api.
Of course, you can also Kill the Yellow prompt by searching for “Guava” in Preferences.
There are many other tips for using Optional, and you can check out Guava and Java8 books and documentation.
Using Optional has the following advantages:
- Wrap defensive programming code beautifully
- Chain calls
- Effectively avoid null Pointers in program code
But it also has some disadvantages:
- Popularity is not ideal, and new team members need to learn the cost
The introduction of Guava in Android requires everyone on the team to either handle the IDEA default prompt or tolerate the yellow prompt
Sometimes code reading might look something like this:
Kotlin
Of course, Kotlin features excellent empty security and can be used well with Java, like this:
test1? .test2? .test3? .test4Copy the code
If you’re already using Kotlin, you don’t have to write defensive nulls. If you’re not already using Kotlin, it’s not recommended to go straight to Kotlin for the sake of elegance.