java代码像kotlin一样不判空

551 阅读1分钟
原文链接: github.com

nonull

客户端使用服务端返回的数据时通常需要各种判空,不判空就可能导致crash, 为此我们经常会写一些这样的代码

     if (country != null
                && country.zhejiang != null
                && country.zhejiang.hangzhou != null
                && country.zhejiang.hangzhou.woman != null
                && country.zhejiang.hangzhou.woman.friends != null) {
            dealWith(country.zhejiang.hangzhou.woman.friends);
     }

判断逻辑占据了大量篇幅,条件语句增多导致代码变得混乱,数据的可靠性应该像网络协议一样,由专门的处理层保证,不应该影响业务逻辑

我们来看一下Kotlin是如何优雅的实现的

Kotlin 类型定义

class Country {
    var shandong: Province? = null
    var zhejiang = Province();
    override fun toString(): String {
        return "Country(shandong=$shandong, zhejiang=$zhejiang)"
    }
}
class Province{
    var qingdao: City? = null
    var hangzhou = City()
    var beijing: City? = null
    override fun toString(): String {
        return "Province(qingdao=$qingdao, hangzhou=$hangzhou, beijing=$beijing)"
    }
}
class City{
    var man: Person? = null
    var woman = Person();
    override fun toString(): String {
        return "City(man=$man, woman=$woman)"
    }
}
class Person{
    var name = "CTS"
    var birth = Date(0)
    var age = Date().year
    var isStudent: Boolean? = true
    var friends: List<Person> = ArrayList()
    var family: ArrayList<Person> = ArrayList()
    var toys: LinkedList<String>? = null
    var brothers = arrayOfNulls<Person>(0)
    var note = arrayOfNulls<Long>(0)
    var map: Map<String, String>? = null
    var mCountry: Country? = null
    override fun toString(): String {
        return "Person(name='$name', birth=$birth, age=$age, isStudent=$isStudent, friends=$friends, family=$family, toys=$toys, brothers=${Arrays.toString(brothers)}, note=${Arrays.toString(note)}, map=$map)"
    }
}

使用

        var country = Country();

        var values = country.zhejiang?.hangzhou?.woman?.birth;
        println(if (values != null) values else "does not exist")


        var birth2 = country.shandong?.hangzhou?.woman?.birth
        println(if (birth2 != null) birth2 else "does not exist")


        var city = country.shandong?.qingdao
        println(if (city != null) city else "does not exist")

        city = country.zhejiang.hangzhou
        println(if (city != null) city else "does not exist")


        val map = country.zhejiang.hangzhou.woman.map
        println(if (map != null) map else "does not exist")


输出


Thu Jan 01 08:00:00 GMT+08:00 1970
does not exist
does not exist
City(man=null, woman=Person(name='CTS', birth=Thu Jan 01 08:00:00 GM...
does not exist

kotlin 引入了可选语法减少了判空,那java想变得同样优雅该怎么办呢?

如何使用nonull

比如我们有如下的几个类

package com.wanjian;

import com.wanjian.test.data.Province;

/**
 * Created by wanjian on 2017/7/24.
 */

public class Country {
    public Province shandong;
    public Province zhejiang = new Province(1);

    @Override
    public String toString() {
        return "Country{" +
                "shandong=" + shandong +
                ", zhejiang=" + zhejiang +
                '}';
    }
}
package com.wanjian.test.data;


import com.wanjian.city.City;
import com.wanjian.nonull.Keep;

/**
 * Created by wanjian on 2017/7/24.
 */

public class Province {
    public City qingdao;
    public City hangzhou = new City();
    @Keep
    public City beijing;
    public Province(int a) {
    }

    @Override
    public String toString() {
        return "Province{" +
                "qingdao=" + qingdao +
                ", hangzhou=" + hangzhou +
                ", beijing=" + beijing +
                '}';
    }
}

package com.wanjian.city;

import com.data.person.Person;

/**
 * Created by wanjian on 2017/7/24.
 */

public class City {
    public Person man;
    public Person woman = new Person();

    @Override
    public String toString() {
        return "City{" +
                "man=" + man +
                ", woman=" + woman +
                '}';
    }
}
package com.data.person;

import com.wanjian.Country;
import com.wanjian.nonull.Keep;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * Created by wanjian on 2017/7/24.
 */

public class Person {
    public String name = "CTS";
    @Keep
    public Date birth = new Date(0);
    public Integer age = new Date().getYear();
    public Boolean isStudent = true;

    public List<Person> friends = new ArrayList<>();
    public ArrayList<Person> family = new ArrayList<>();
    public LinkedList<String> toys;
    public Person[] brothers = new Person[0];
    public Long[] note = new Long[0];
    public Map<String, String> map;
    public Country mCountry;

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", birth=" + birth +
                ", age=" + age +
                ", isStudent=" + isStudent +
                ", friends=" + friends +
                ", family=" + family +
                ", toys=" + toys +
                ", brothers=" + Arrays.toString(brothers) +
                ", note=" + Arrays.toString(note) +
                ", map=" + map +
                ", mCountry=" +
                '}';
    }
}

我们只需要这样使用

import static com.wanjian.nonull.NoNull.$;
import static com.wanjian.nonull.NoNull.?;

public class Test {
    public static void main(String[] args) {
        init();
//        List<String> list = NoNull.?(null, List.class);
        Country country = ?(new Country(), Country.class);
        System.out.println(country);

        Date birth = country.zhejiang.hangzhou.woman.birth;
        System.out.println($(birth) ? birth : "does not exist");

        birth = country.shandong.hangzhou.woman.birth;
        System.out.println($(birth) ? birth : "does not exist");

        City city = country.shandong.qingdao;
        System.out.println($(city) ? city : "does not exist");
        city = country.zhejiang.hangzhou;
        System.out.println($(city) ? city : "does not exist");


        Map map = country.zhejiang.hangzhou.woman.map;
        System.out.println($(map) ? map : "does not exist");
    }
}

输出

Thu Jan 01 08:00:00 CST 1970
does not exist
does not exist
City{man=Person{name='', birth=null, age=-214748...
does not exist

语法比Kotlin还要简单,只需要把最外层的对象传递给 NoNull.?()即可得到一个非空的对象, 可以调用这个对象所有字段都不会是空,除非对象中的字段使用了 com.wanjian.nonull.Keep 注解,可以使用NoNull.$()判断一个对象是否存在。具体用法参考com.test.Test