プロジェクト内で発生した無数の null 判定は、コードの品質とクリーンさに非常に悪影響を及ぼしており、私たちはこの現象を「null 判定災害」と呼んでいます。
それでは、この現象はどのように管理すればよいのでしょうか? NullObject パターンについて聞いたことがあるかもしれませんが、これは今日の私たちの武器ではありませんが、それでも NullObject パターンを導入する必要があります。
オブジェクト指向コンピュータ プログラミングでは、null オブジェクトは、参照される値がないか、中立 (「null」) の動作が定義されているオブジェクトです。null オブジェクトの設計パターンでは、そのようなオブジェクトの使用方法とそのオブジェクトの使い方について説明します。行動 (またはその欠如)。
上記の分析は Wikipedia から引用したものです。
NullObject パターンは、書籍「プログラミング パターン ランゲージ」シリーズで初めて出版されました。一般に、オブジェクト指向言語では、null 参照では必要なメソッドを呼び出すことができないため、オブジェクトを呼び出す前に null チェックを使用して、これらのオブジェクトが null かどうかを判断する必要があります。
サンプル コードは次のとおりです (名前はインターネットから来ています。笑、なんて怠け者でしょう):
Nullable は空のオブジェクトに関連する操作インターフェイスであり、空のオブジェクトに関連する操作インターフェイスです。オブジェクトは空です。空オブジェクト モードでは、オブジェクトが空の場合、オブジェクトはオブジェクトにパッケージ化され、Null オブジェクトになります。このオブジェクトは、元のオブジェクトのすべてのメソッドの null 実装を実装します...
public interface Nullable { boolean isNull(); }
このインターフェイスはビジネス オブジェクトの動作を定義します。
<br>
public interface DependencyBase extends Nullable { void Operation(); }
これはオブジェクトの実際のクラスで、ビジネス動作インターフェイスのDependencyBaseと空のオブジェクト操作インターフェイスのNullableを実装します。
public class Dependency implements DependencyBase, Nullable { @Override public void Operation() { System.out.print("Test!"); } @Override public boolean isNull() { return false; } }
これは空のオブジェクトで、元のオブジェクトの動作を実装します。
public class NullObject implements DependencyBase{ @Override public void Operation() { // do nothing } @Override public boolean isNull() { return true; } }
使用時には、空のオブジェクトはファクトリ呼び出しを通じて呼び出すことも、リフレクション (通常は数ミリ秒かかります) などの他のメソッドを通じてオブジェクトを呼び出すこともできますが、ここでは詳しく説明しません。
public class Factory { public static DependencyBase get(Nullable dependencyBase){ if (dependencyBase == null){ return new NullObject(); } return new Dependency(); } }
これは使用例です。このモードを使用すると、オブジェクトの null 操作を実行する必要がなくなり、NPE (NullPointerException) を気にせずにオブジェクトを直接使用できるようになります。
public class Client { public void test(DependencyBase dependencyBase){ Factory.get(dependencyBase).Operation(); } }
NR Null Object は、Android Studio、IntelliJ IDEA、PhpStorm、WebStorm、PyCharm、RubyMine、AppCode、CLion、GoLand、DataGrip およびその他の IDEA プラグインに適した Intellij です。 。既存のオブジェクトに基づいて空のオブジェクト モードに必要なコンポーネントを迅速かつ簡単に生成できます。その機能には次のものが含まれます:
インターフェイスとして宣言できる選択されたクラスのメソッドを分析する;
パブリック インターフェイスを抽象化する;
空のオブジェクトを作成し、パブリック インターフェイスを自動的に実装します;
一部の関数では、null 許容宣言を作成します。
関数を追加して再生成できます。
自動関数命名規則
どうですか? とても速くて便利そうです。空にするだけで十分です。 -元のオブジェクトで複数回チェックされました。電子メール ポップアップ メニューで、[生成] を選択し、[NR Null オブジェクト] を選択して、対応する Null オブジェクト コンポーネントを自動的に生成します。
IDEA の環境設定のプラグイン リポジトリから直接インストールできます。
##あいまいクエリの場合は「NR Null Oject」または「Null Oject」を検索しますをクリックし、右側の「インストール」をクリックして IDEA を再起動します。 Optionalもう 1 つの方法は、Java8 機能の Optional を使用して、エレガントな空判定を実行することです。Optional の正式な紹介は次のとおりです。 #null 以外の値を含む場合と含まない場合があるコンテナ オブジェクト。値が存在する場合、isPresent() は true を返し、get() は値を返します。環境設定を選択 → プラグイン → リポジトリを参照
null 以外の値が含まれる場合も含まれない場合もあるコンテナ オブジェクト。値が存在する場合、isPresent() は true を返し、get() は値を返します。
早速、例を挙げてみましょう。
次のコードがあります。Test2 で Info 情報を取得する必要がありますが、パラメーターは Test4 です。レイヤーごとに適用する必要があります。各レイヤーで取得されたオブジェクトは空である可能性があります。最終的なコードは次のようになります。そのようです。
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">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(); }</pre><div class="contentsignin">ログイン後にコピー</div></div>
しかし、Optional を使用すると、すべてが異なります。
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">public String testOptional(Test test) { return Optional.ofNullable(test).flatMap(Test::getTest3) .flatMap(Test3::getTest2) .map(Test2::getInfo) .orElse(""); }</pre><div class="contentsignin">ログイン後にコピー</div></div>
1. Optional.ofNullable(test)、test が空の場合、シングルトンの空の Optional オブジェクトが返されます。空でない場合は、Optional パッケージング オブジェクトが返されます。 test. ;
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">public static <t> Optional<t> ofNullable(T value) { return value == null ? empty() : of(value); }</t></t></pre><div class="contentsignin">ログイン後にコピー</div></div>
2. flatMap(Test::getTest3) は、test が空かどうかを判断します。空の場合は、最初のステップでシングルトンの Optional オブジェクトを返し続けます。そうでない場合は、呼び出します。テストの getTest3 メソッド;
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">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></pre><div class="contentsignin">ログイン後にコピー</div></div>
<p>3、flatMap(Test3::getTest2)同上调用Test3的getTest2方法;</p>
<p>4、map(Test2::getInfo)同flatMap类似,但是flatMap要求Test3::getTest2返回值为Optional类型,而map不需要,flatMap不会多层包装,map返回会再次包装Optional;<code>
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
以上がJavaで空判定を実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。