JDK8新特性之:Optional

痛點(diǎn)

在java編碼過程中兵拢,大家碰到的最多的異常是什么介褥,我相信必然這貨NullPointerException必然是排行第一的。那我們在平時編碼中曲聂,有各種編碼規(guī)范與其相關(guān)霹购,比如時時的判斷null,方法禁止返回null等朋腋,例如

public void bindUserToRole(User user) {
    if (user != null) {
        String roleId = user.getRoleId();
        if (roleId != null) {
            Role role = roleDao.findOne(roleId);
            if (role != null) {
                role.setUserId(user.getUserId());
                roleDao.save(role);
            }
        }
    }
}

或者

public String bindUserToRole(User user) {
    if (user == null) {
        return;
    }

    String roleId = user.getRoleId();
    if (roleId == null) {
        return;
    }

    Role = roleDao.findOne(roleId);
    if (role != null) {
        role.setUserId(user.getUserId());
        roleDao.save(role);
    }
}

為了防止NullPointerException齐疙,好好的代碼寫成這個鳥樣,或許下面的會看上去比較順眼一點(diǎn)旭咽,但是大體還是一樣的贞奋。
其實(shí)我們有一種更為優(yōu)雅的方式來完成上面的功能,如下

Optional<String> roleOpt = Optional.ofNullable(user).map(User::getRoleId);
if(roleOpt.isPresent()){
    ....
}

這樣穷绵,我們僅需要對我們關(guān)心的做一次校驗轿塔,省卻了前面的一系列的檢驗操作。

Optional的引入

基于上述的一些原因请垛,在JDK8中催训,引入了一個新的類java.util.Optional,來避免這類問題的處理宗收。
先看下類的說明

A container object which may or may not contain a non-null value.If a value is present, isPresent()will return true andget() will return the value.

這里面說明這是一個可以包含null或者非null的容器漫拭,其最基本的兩個操作就是isPresent()get(),基本用起來就是這樣

if( oneOptional.isPresent() ){
     String s = oneOptional.get();
    ....
}

首先我們看下這個類中包含哪些方法混稽,如下

image.png

首先采驻,其有一個成員變量和一個定義的常量如下

   private static final Optional<?> EMPTY = new Optional<>();
   private final T value;

其中value表示其封裝的真實(shí)的對象,EMPTY是定義的一個表示空的常量匈勋。構(gòu)造方法很很簡單礼旅,兩個常見的私有構(gòu)造方法Optional()Optional(T),其中不帶參的默認(rèn)設(shè)置valuenull洽洁,帶參的構(gòu)造函數(shù)痘系,不允許傳null

Optional類包含3個靜態(tài)方法生成Optional對象饿自,分別為

  • Optional<T> empty()
    生成一個空Optional對象汰翠,其valuenull
  • Optional<T> of(T value)
    調(diào)用Optional(T)構(gòu)造方法龄坪,其value不允許為null
  • Optional<T> ofNullable(T value)
    Optional<T> of(T value)的差別是其傳入的value允許為null

下面簡單介紹一下里面的各個方法和一些簡單的使用示例

  • get()
    返回value,若為null則拋出異常NoSuchElementException
  • isPresent()
    判斷當(dāng)前的value是否為null
  • ifPresent(Consumer<? super T> consumer)
    該方法支持傳入一個Consumer對象复唤,當(dāng)value不為null的時候調(diào)用健田,為null則不做任何操作,示例如下
    public void testIfPresent(){
        Optional<String> optional=Optional.of("zh");
        optional.ifPresent(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });
    }

配合lambda使用佛纫,代碼更為簡潔

    public void testIfPresent(){
        Optional<String> optional=Optional.of("zh");
        optional.ifPresent(s -> System.out.println(s));
    }
  • filter(Predicate<? super T> predicate)
    顧名思義妓局,這個方法的作用就是filter(過濾),該方法用于過濾一個Optional對象呈宇,通過傳入的Predicate對象中的一個test方法好爬,例如
        Optional<String> optional=Optional.of("aa");
        Optional<String> optionalResult=optional.filter(s -> s.startsWith("a"));
        System.out.println(optionalResult);

輸出結(jié)果是

Optional[aa]

由于其返回仍是一個Optional對象,我們可以有如下較為優(yōu)雅的寫法

Optional<String> optionalResult=optional.filter(s -> s.startsWith("a"))
                .filter(s -> s.length()==2)
                .filter(s -> s.endsWith("a"));
  • map(Function<? super T, ? extends U> mapper)
    此方法支持一個Function參數(shù)攒盈,在這個Function里面可以對這個Optional對象做一些操作或者改變抵拘,其返回值仍為一個Optional類型,例如
Optional<String> optional=Optional.of("aa");
        Optional<Integer> result= optional.map(s -> s.toUpperCase())
                .map(s->s.length());

輸出結(jié)果為

Optional[2]

map提供一種優(yōu)雅的流式的方式來替代先前繁雜的if判斷和數(shù)據(jù)處理

  • flatMap(Function<? super T, Optional<U>> mapper)
    map類似型豁,只不過需要我們手動將方法的返回僵蛛,封裝成Optional對象,如
Optional<Integer> result= optional.flatMap(s -> Optional.of(s.toUpperCase()))
                .flatMap(s -> Optional.of(s.length()));

其余功能與map一致 迎变。

  • orElse(T other)
    這個方法較為簡單充尉,參數(shù)為一個默認(rèn)值,即若valuenull衣形,則返回默認(rèn)值
        Optional<String> optional=Optional.of("aa");
        System.out.println(optional.orElse("bb"));
        Optional<String> optional1=Optional.ofNullable(null);
        System.out.println(optional1.orElse("bb"));

輸出為

aa
bb
  • orElseGet(Supplier<? extends T> other)
    提供一個Supplier入?yún)⑼障溃?code>Supplier提供一個默認(rèn)值,例如
    Optional<String> optional=Optional.ofNullable(null);
    System.out.println(optional.orElseGet(() -> "aaa"));
  • orElseThrow(Supplier<? extends X> exceptionSupplier)
    顧名思義谆吴,若為null則拋出異常
        Optional<String> optional=Optional.ofNullable(null);
        System.out.println(optional.orElseThrow(() -> new RuntimeException()));

使用場合注意

Reports calls to java.util.Optional.get() without first checking with a isPresent() call if a value is available. If the Optional does not contain a value, get() will throw an exception.

Optional.get() 前不事先用 isPresent() 檢查值是否可用. 假如 Optional 不包含一個值, get() 將會拋出一個異常

Reports any uses of java.util.Optional<T>, java.util.OptionalDouble, java.util.OptionalInt, java.util.OptionalLong or com.google.common.base.Optional as the type for a field or a parameter. Optional was designed to provide a limited mechanism for library method return types where there needed to be a clear way to represent “no result”. Using a field with type java.util.Optional is also problematic if the class needs to be Serializable, which java.util.Optional is not

使用任何像 Optional 的類型作為字段或方法參數(shù)都是不可取的. Optional 只設(shè)計為類庫方法的, 可明確表示可能無值情況下的返回類型. Optional 類型不可被序列化, 用作字段類型會出問題的

借鑒

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末倒源,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子句狼,更是在濱河造成了極大的恐慌笋熬,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腻菇,死亡現(xiàn)場離奇詭異胳螟,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)筹吐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進(jìn)店門糖耸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人丘薛,你說我怎么就攤上這事嘉竟。” “怎么了?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵周拐,是天一觀的道長铡俐。 經(jīng)常有香客問我,道長妥粟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任吏够,我火速辦了婚禮勾给,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘锅知。我一直安慰自己播急,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布售睹。 她就那樣靜靜地躺著桩警,像睡著了一般。 火紅的嫁衣襯著肌膚如雪昌妹。 梳的紋絲不亂的頭發(fā)上捶枢,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天,我揣著相機(jī)與錄音飞崖,去河邊找鬼烂叔。 笑死,一個胖子當(dāng)著我的面吹牛固歪,可吹牛的內(nèi)容都是我干的蒜鸡。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼牢裳,長吁一口氣:“原來是場噩夢啊……” “哼逢防!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蒲讯,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤忘朝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后伶椿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辜伟,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年脊另,在試婚紗的時候發(fā)現(xiàn)自己被綠了导狡。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡偎痛,死狀恐怖旱捧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤枚赡,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布氓癌,位于F島的核電站,受9級特大地震影響贫橙,放射性物質(zhì)發(fā)生泄漏贪婉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一卢肃、第九天 我趴在偏房一處隱蔽的房頂上張望疲迂。 院中可真熱鬧,春花似錦莫湘、人聲如沸尤蒿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽腰池。三九已至,卻和暖如春忙芒,著一層夾襖步出監(jiān)牢的瞬間示弓,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工匕争, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留避乏,地道東北人。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓甘桑,卻偏偏與公主長得像拍皮,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子跑杭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評論 2 361

推薦閱讀更多精彩內(nèi)容

  • Java 8自Java 5(發(fā)行于2004)以來最具革命性的版本铆帽。Java 8 為Java語言、編譯器德谅、類庫爹橱、開發(fā)...
    誰在烽煙彼岸閱讀 891評論 0 4
  • 目錄結(jié)構(gòu) 介紹 Java語言的新特性2.1 Lambdas表達(dá)式與Functional接口2.2 接口的默認(rèn)與靜態(tài)...
    夜風(fēng)月圓閱讀 477評論 0 2
  • 前言:Java 8 已經(jīng)發(fā)布很久了,很多報道表明Java 8 是一次重大的版本升級窄做。在Java Code Geek...
    糖寶_閱讀 1,323評論 1 1
  • 和我關(guān)系很好的一個女孩子椭盏,新婚不久组砚,每次跟我聊天,總會跟我抱怨她老公的種種不是掏颊,總是跟我抱怨她老公家里人的各種不好...
    沸騰_6d31閱讀 582評論 0 0
  • 《死亡詩社》 1.概念 威爾頓預(yù)備學(xué)院以其沉穩(wěn)凝重的教學(xué)風(fēng)格和較高的升學(xué)率聞名糟红,作為其畢業(yè)班的學(xué)生艾帐,理想就是升入名...
    昔瞳_1404閱讀 225評論 2 2