为了程序的健壮性,我们可以使用空对象模式

空对象模式 (null object Pattern)是一种软件设计模式。可以用于返回无意义的对象时,它可以承担处理null的责任。有时候空对象也被视为一种设计模式。

在写代码的时候我们经常会遇到空指针,为了避免空指针的发生需要做一些判断。如果是复杂对象的话,还需要一层层地去判断。这个时候我就无比怀念groovy、kotlin这类语言。可以使用形如:

     user?.address?.name

这样的语法糖,而无需一层层的判断。

google的guava库提供了Optional类,可以有效的判断null对象。

Optional<Integer> possible = Optional.of(5);
possible.isPresent(); // returns true
possible.get(); // returns 5

guava可以创建指定的null对象

Optional<Integer> nullable=Optional.fromNullable(null);
System.out.println("from Nullable Optional isPresent:"+nullable.isPresent());  //returns from Nullable Optional isPresent:false

在java 8中也新增了Optional类。

同时,我自己也仿照guava的Optional类写了一个简化版的Optional并附上使用方法,它借助了rxjava。

import rx.Observable;

/**
 * 使用方法:
 *      String s = null;
 *      Optional.ofNullable(s).orElse("default")); // 如果s为null,则显示default,否则显示s的值
 * @author Tony Shen
 *
 */
public class Optional<T> {

    Observable<T> obs;

    public Optional(Observable<T> obs) {
        this.obs = obs;
    }

    public static <T> Optional<T> of(T value) {
        if (value == null) {
            throw new NullPointerException();
        } else {
            return new Optional<T>(Observable.just(value));
        }
    }

    public static <T> Optional<T> ofNullable(T value) {
        if (value == null) {
            return new Optional<T>(Observable.<T>empty());
        } else {
            return new Optional<T>(Observable.just(value));
        }
    }

    public T get() {
        return obs.toBlocking().single();
    }

    public T orElse(T defaultValue) {
        return obs.defaultIfEmpty(defaultValue).toBlocking().single();
    }
}

上面讲了那么多,是为了防止空指针出现,现在我们来看看空对象模式具体的使用场景吧,假设我们在代码中使用了链式调用,形如:

client = RestClient.post(request.getUrl())
        .readTimeout(request.getReadTimeoutMillis())
        .connectTimeout(request.getConnectTimeoutMillis())
        .addHeaders(request.getHeaders());

只要某一个环节出现问题,就会有空指针的隐患的。比如RestClient的post()方法内部出现了问题,那就非常严重了,后面整个链路都会断掉,报空指针异常。

那我们如何保证整个链路不断呢?在post()方法里面会调用一个getConnection()方法

    public HttpURLConnection getConnection() {
        if (connection == null)
            connection = createConnection();

        if (connection == null) {
            clientIsNull = true;
            connection = NullConnection.createNull(url);
        }
        return connection;
    }

请注意,在getConnection()方法里会有两个connection == null的判断。理论上,第一次调用createConnection()方法时,connection是不会为空的。但是在使用某个APM sdk时,确实发现有极少的概率connection会为空。如果它为空,那么我们在第二个判断中增加了如下的代码,来保证返回的connection不为null,提高程序的健壮性。

   connection = NullConnection.createNull(url);

我们来看看,NullConnection是怎么回事

/**
 * Created by Tony Shen on 2016/12/6.
 */

public class NullConnection extends HttpURLConnection {

    private NullConnection(URL url) {
        super(url);
    }

    @Override
    public void disconnect() {

    }

    @Override
    public boolean usingProxy() {
        return false;
    }

    @Override
    public void connect() throws IOException {

    }

    public boolean isNull() {
        return true;
    }

    public static NullConnection createNull(URL url) {
        return new NullConnection(url);
    }
}

其实,基本没做啥事,主要多了一个createNull()的方法。它会产生一个NullConnection对象,它的作用是防止产生null,从而保证原先的RestClient链路是正常的。这就是空对象模式。

链式调用,会让代码更加清晰,带给我们的好处是非常明显的。只要我们处理好空指针的隐患,就可以更愉悦地写代码了O(∩_∩)O哈哈~

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏带你撸出一手好代码

浅谈 var 关键字

提起 var关键子,程序员的第一反应就是JavaScript, 事实上这个关键子在其他语言中也有被采用。 比如说C#, 比如说kotlin, 用法和JavaSc...

29680
来自专栏python3

习题27:if和else

if语句为代码创建了一个所谓的"分支",就跟RPG游戏中的情节分支一样,if语句告诉你的脚本:“如果这个布尔表达式为真,就运行接下来的代码,否则就跳过这一段”

6710
来自专栏数据结构与算法

1487 大批整数排序

个人博客:doubleq.win 1487 大批整数排序  时间限制: 3 s  空间限制: 16000 KB  题目等级 : 黄金 Gold 题解 题目描述 ...

30360
来自专栏分布式系统和大数据处理

C#中的泛型

.Net 1.1版本最受诟病的一个缺陷就是没有提供对泛型的支持。通过使用泛型,我们可以极大地提高代码的重用度,同时还可以获得强类型的支持,避免了隐式的装箱、拆箱...

10470
来自专栏Danny的专栏

数据脱敏——基于Java自定义注解实现日志字段脱敏

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

1.3K10
来自专栏为数不多的Android技巧

[译]厌倦了NullPointException?Optional拯救你!

有人说,当你处理过了空指针异常才真正成为一个Java开发者。抛开玩笑话不谈,空指针确实是很多bug的根源。Java SE 8引入了一个新的叫做java.util...

12720
来自专栏加米谷大数据

多面编程语言Scala

如Scala官网宣称的:“Object-OrientedMeetsFunctional”,这一句当属对Scala最抽象的精准描述,它把近二十年间大行其道的面向对...

30040
来自专栏互扯程序

Java开发中遇到的那些坑!

之前在这个手册刚发布的时候看过一遍,当时感觉真是每个开发者都应该必读的一本手册,最近由于在总结一些我们日常开发中容易忽略的问题,可能是最低级的编码常见问题,往往...

8310
来自专栏架构之路

索引优先队列-IndexedPrirotyQueue的原理及实现(源码)

1.索引优先队列的意义 索引优先队列是一个比较抽象的概念,它是一个优先队列,又带有索引,这个索引是用来干什么的呢? 在正常的队列中,我们只能访问队列头元素,整个...

47980
来自专栏转载gongluck的CSDN博客

python笔记:#009#判断语句

判断(if)语句 目标 开发中的应用场景 if 语句体验 if 语句进阶 综合应用 01. 开发中的应用场景 生活中的判断几乎是无所不在的,我们每天都在做各种各...

43340

扫码关注云+社区

领取腾讯云代金券