프로젝트에서 수많은 Null 판단이 코드 품질과 청결도에 매우 나쁜 영향을 미쳤습니다. 우리는 이 현상을 "Null 판단 재앙"이라고 부릅니다.
그렇다면 이 현상을 어떻게 관리해야 할까요? NullObject 패턴에 대해 들어보셨겠지만 이것이 오늘날 우리의 무기는 아니지만 여전히 NullObject 패턴을 도입해야 합니다.
객체 지향 컴퓨터 프로그래밍에서 null 객체는 참조된 값이 없거나 정의된 중립("null") 동작이 있는 객체입니다. null 객체 디자인 패턴은 이러한 객체의 사용과 해당 동작(또는 객체의 부족)을 설명합니다. .
위의 분석은 위키피디아에서 나온 것입니다.
NullObject 패턴은 "프로그래밍 패턴 언어" 시리즈에서 처음 공개되었습니다. 일반적으로 객체 지향 언어에서는 null 참조에서는 필수 메서드를 호출할 수 없기 때문에 객체를 호출하기 전에 null 검사를 사용하여 이러한 객체가 null인지 확인해야 합니다.
샘플 코드는 다음과 같습니다(이름은 인터넷에서 따온 이름입니다. 하하, 얼마나 게으르신가요?).
Nullable은 빈 개체의 관련 작업 인터페이스로, 개체가 비어 있는지 확인하는 데 사용됩니다. 빈 개체 모드에서는 개체가 비어 있으면 패키지화됩니다. 개체가 되고 Null 개체가 됩니다. 이 개체는 원본 개체의 모든 메서드에 대한 null 구현을 구현합니다...
public interface Nullable { boolean isNull(); }
이 인터페이스는 개체의 동작을 정의합니다. 비즈니스 객체.
<br>
public interface DependencyBase extends Nullable { void Operation(); }
이것은 비즈니스 동작 인터페이스인 dependencyBase와 null 개체 작업 인터페이스인 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로 선언합니다.
자동 함수 명명 규칙을 추가할 수 있습니다.
사용 예를 살펴보겠습니다.이 플러그인을 얻는 방법은 무엇입니까?
기본 설정 선택 → 저장소 탐색
또 다른 방법은 Java8의 Optional 기능을 사용하여 null 값을 우아하게 결정하는 것입니다. Optional의 공식 소개는 다음과 같습니다. null이 아닌 값을 포함할 수도 있고 포함하지 않을 수도 있는 컨테이너 개체입니다. 값이 있으면 isPresent()는 true를 반환하고 get()은 값을 반환합니다.Optional
null이 아닌 값을 포함할 수도 있고 포함하지 않을 수도 있는 컨테이너 개체입니다. 값이 있으면 isPresent()는 true를 반환하고 get()은 값을 반환합니다.
더 이상 고민하지 않고 예를 들어 보겠습니다. Test2에서 Info 정보를 얻어야 하는 다음 코드가 있는데, 매개변수는 Test4입니다. 각 레이어에서 얻은 객체는 비어 있을 수 있습니다.
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(); }
2. flatMap(Test::getTest3)은 테스트가 비어 있는지 확인합니다. 비어 있으면 첫 번째 단계에서 계속해서 싱글톤 Optional 개체를 반환하고, 그렇지 않으면 Test의 getTest3 메서드를 호출합니다. 코드>public String testOptional(Test test) { return Optional.ofNullable(test).flatMap(Test::getTest3) .flatMap(Test3::getTest2) .map(Test2::getInfo) .orElse(""); }로그인 후 복사1. Optional.ofNullable(test), test가 비어 있으면 Optional 포장 개체가 test를 래핑하여 반환됩니다. code >
public static <t> Optional<t> ofNullable(T value) { return value == null ? empty() : of(value); }</t></t>로그인 후 복사
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
위 내용은 Java에서 빈 판단을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!