Home >Java >javaTutorial >How to implement empty judgment in Java
Countless null judgments in the project have had a very bad impact on the code quality and cleanliness. We call this phenomenon "null judgment disaster".
So, how to manage this phenomenon? You may have heard of the NullObject pattern, but this is not our weapon today, but we still need to introduce the NullObject pattern.
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 comes from Wikipedia.
The NullObject pattern was first published in the "Programming Pattern Language" series of books. Generally, in object-oriented languages, you need to use a null check before calling objects to determine whether these objects are null, because the required methods cannot be called on null references.
The sample code is as follows (the name comes from the Internet, haha, how lazy is it):
Nullable is the related operation interface of the empty object, used to determine whether the object is empty, because in the empty object mode , if the object is empty, it will be packaged into an Object and become Null Object. This object will implement null implementations of all methods of the original object...
public interface Nullable { boolean isNull(); }
This interface defines the behavior of the business object.
<br>
public interface DependencyBase extends Nullable { void Operation(); }
This is the real class of the object, which implements the business behavior interface DependencyBase and the empty object operation interface Nullable.
public class Dependency implements DependencyBase, Nullable { @Override public void Operation() { System.out.print("Test!"); } @Override public boolean isNull() { return false; } }
This is an empty object, which implements the behavior of the original object.
public class NullObject implements DependencyBase{ @Override public void Operation() { // do nothing } @Override public boolean isNull() { return true; } }
When in use, the empty object can be called through factory calling, or the object can be called through other methods such as reflection (usually taking a few milliseconds), which will not be described in detail here.
public class Factory { public static DependencyBase get(Nullable dependencyBase){ if (dependencyBase == null){ return new NullObject(); } return new Dependency(); } }
This is a usage example. Through this mode, we no longer need to perform the null operation of the object, but can use the object directly without worrying about NPE (NullPointerException).
public class Client { public void test(DependencyBase dependencyBase){ Factory.get(dependencyBase).Operation(); } }
NR Null Object is an Intellij suitable for Android Studio, IntelliJ IDEA, PhpStorm, WebStorm, PyCharm, RubyMine, AppCode, CLion, GoLand, DataGrip and other IDEAs plugin. It can quickly and easily generate the components required for its empty object mode based on existing objects. Its functions include the following:
Analyze the methods of the selected class that can be declared as interfaces;
Abstract the public interface;
Create an empty object and automatically implement the public interface;
For some functions Make a nullable declaration;
You can append functions to generate again;
Automatic function naming convention
How about it? It seems very fast and convenient. It only needs to be empty-checked multiple times on the original object. In the email pop-up menu, select Generate, and select NR Null Object to automatically generate the corresponding null object component.
Can be installed directly through the Plugins repository in IDEA's Preferences.
##Search for "NR Null Oject" or "Null Oject" for fuzzy query , click Install on the right and restart IDEA. OptionalAnother way is to use the Optional in the Java8 feature to perform elegant empty judgment. The official introduction of Optional is as follows:Select Preferences → Plugins → Browse repositories
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 the value is present, isPresent() will return true and get() will return the value. Without further ado, let me give you an example. There is the following code, which needs to obtain the Info information in Test2, but the parameter is Test4. We need to apply layer by layer. The objects obtained at each layer may be empty. The final code looks like so.
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(); }But after using 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(""); }1. Optional.ofNullable(test), if test is empty, a singleton empty Optional object is returned. If it is not empty, an Optional packaging object is returned. Optional wraps test. ;
public static <t> Optional<t> ofNullable(T value) { return value == null ? empty() : of(value); }</t></t>2. flatMap(Test::getTest3) determines whether test is empty. If it is empty, continue to return the singleton Optional object in the first step, 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 { return Objects.requireNonNull(mapper.apply(value)); } }</u></u></u>
3、flatMap(Test3::getTest2)同上调用Test3的getTest2方法;
4、map(Test2::getInfo)同flatMap类似,但是flatMap要求Test3::getTest2返回值为Optional类型,而map不需要,flatMap不会多层包装,map返回会再次包装Optional;
public<u> Optional<u> map(Function super T, ? extends U> mapper) { Objects.requireNonNull(mapper); if (!isPresent()) return empty(); else { return Optional.ofNullable(mapper.apply(value)); } }</u></u>
5、orElse("");获得map中的value,不为空则直接返回value,为空则返回传入的参数作为默认值。
public T orElse(T other) { return value != null ? value : other; }
怎么样,使用Optional后我们的代码是不是瞬间变得非常整洁,或许看到这段代码你会有很多疑问,针对复杂的一长串判空,Optional有它的优势,但是对于简单的判空使用Optional也会增加代码的阅读成本、编码量以及团队新成员的学习成本。毕竟Optional在现在还并没有像RxJava那样流行,它还拥有一定的局限性。
如果直接使用Java8中的Optional,需要保证安卓API级别在24及以上。
你也可以直接引入Google的Guava。(啥是Guava?来自官方的提示)
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!
引用方式,就像这样:
dependencies { compile 'com.google.guava:guava:27.0-jre' // or, for Android: api 'com.google.guava:guava:27.0-android' }
不过IDEA默认会显示黄色,提示让你将Guava表达式迁移到Java Api上。
当然,你也可以通过在Preferences搜索"Guava"来Kill掉这个Yellow的提示。
将防御式编程代码完美包装
链式调用
有效避免程序代码中的空指针
流行性不是非常理想,团队新成员需要学习成本
安卓中需要引入Guava,需要团队每个人处理IDEA默认提示,或者忍受黄色提示
当然,Kotlin以具有优秀的空安全性为一大特色,并可以与Java很好的混合使用,like this:
test1?.test2?.test3?.test4
The above is the detailed content of How to implement empty judgment in Java. For more information, please follow other related articles on the PHP Chinese website!