java8-04-其他特性

[TOC]

1 原生Base64 API

對應Base64的操作,沒必要非要用第三方庫了。java8內(nèi)置的Base64 API位于 : java.util.Base64


// 編碼 --> 字節(jié)數(shù)組
byte[] bs = Base64.getEncoder().encode("java 8".getBytes(Charset.forName("UTF-8")));
// amF2YSA4
System.out.println(new String(bs));

// 編碼 --> 直接轉(zhuǎn)為String
String string = Base64.getEncoder().encodeToString("java 8".getBytes(Charset.forName("UTF-8")));
// amF2YSA4
System.out.println(string);

// 解碼
byte[] bs2 = Base64.getDecoder().decode(bs);
// java 8
System.out.println(new String(bs2));

2 為NPE而生的Optional容器

為空指針而生的Optional,貌似N就之前就在 google的 工具類 Guava中出現(xiàn)了洒嗤。

public final class Optional<T> {
    private final T value;
    
    private Optional(T value) {
      // value為null時,在這一步就會直接報錯,可以快速定位到NPE發(fā)生的位置
        this.value = Objects.requireNonNull(value);
    }
  
    private Optional() {
        this.value = null;
    }
  
    // 返回一個空的Optional實例
    public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }
    
    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }
   
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }
    // ...
}

其實就是一個容器類绿满,將可能為空的對象包裝在容器中蒿赢。

獲取Optional實例

構(gòu)造器是私有的,可以通過以下方法獲取其實例:

// 1. 返回一個空的Optional實例
Optional<Object> empty = Optional.empty();

// 2. 內(nèi)部調(diào)用了有參數(shù)的構(gòu)造器,因此value != null 的情況下才能正常返回Optional實例
Optional.of(T value);

// 3. value可以是null
ofNullable(T value);

常用方法

  • isPresent() : 如果值存在返回true泳赋,否則返回false
  • get(): 容器內(nèi)部有值則將其返回,否則拋出NoSuchElementException
  • orElse(T other): 容器內(nèi)部有值則將其返回,否則返回other
  • orElseGet(Supplier<? extends T> other): 容器內(nèi)部有值則將其返回,否則返回供給型接口other的返回值
  • orElseThrow(Supplier<? extends X> exceptionSupplier): 容器內(nèi)部有值則將其返回,否則拋出供給型接口other返回的異常
  • filter(Predicate<? super T> predicate): 對容器中的值使用predicate過濾后,如果滿足條件則返回包含該值的Optional,否則返回空Optional
  • map(Function<? super T, ? extends U> mapper): 該方法的源碼如下
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
    // mapper不能是null
    Objects.requireNonNull(mapper);
    // 容器內(nèi)沒有值,返回空Optional
    if (!isPresent())
        return empty();
    else {
        // 容器內(nèi)有值,返回對容器中的值apply隱射函數(shù)后的值的Optional
         return Optional.ofNullable(mapper.apply(value));
    }
}

使用Optional

先來看一種別扭的寫法

Optional<User> user = ......;
if (user.isPresent()) {// 容器內(nèi)部的對象存在就使用它
    return user.get().getName();
} else {// 否則返回默認值
    return "default Value";
}

其實,這樣用和下面的寫法沒有任何區(qū)別:

User user = ......;
if (user != null) {
    return user.getName();
} else {
    return "default Value";
}

調(diào)用方法 isPresent() , 其實和 obj!=null 是一模一樣的妇菱。

有了Optional,像下面這樣才比較優(yōu)雅:

Optional<User> user = ......;
return user.map(User::getName).orElse("default Value");

再來看個例子

public static class Person {
    private String name;
    private Addr addr;

    public static class Addr {
        private String city;
        private String street;
    }
}
// 獲取用戶的街道名,如果為空,返回"NotFound"
public String getPersonStreet(Person person) {
    return Optional.ofNullable(person)//
      .map(p -> p.getAddr())//
      .map(a -> a.getStreet())//
      .orElse("NotFound");
}


// 沒有Optional的時候,這個功能很可能就得這么寫了
public String getPersonStreet2(Person person) {
    if (person != null) {
        if (person.getAddr() != null) {
            if (person.getAddr().getStreet() == null) {
                return "NotFound";
            }
            return person.getAddr().getStreet();
        }
    }
    return "NotFound";
}

總結(jié)

  • Optional的出現(xiàn),并不是能夠避免NPE,只是能減少NPE的發(fā)生。-
  • 在NPE發(fā)生時,Optional可以快速定位NPE的根源

同時,在使用Optional的時候,應該盡量避免那些不優(yōu)雅的寫法,不然Optional的出現(xiàn)及幾乎沒有任何意義了。鑒于此,有以下幾點建議:

  • 盡量不要直接調(diào)用 isPresent()/get() 方法
  • 不建議將Optional作為成員變量/方法入?yún)?/li>
  • 應該盡量使用 map()/filter()/orElse() 等方法

3 升級版的interface

public interface Foo {

    // 傳統(tǒng)的全區(qū)靜態(tài)常量
    Integer max = 10000;
    
    // 傳統(tǒng)的抽象方法
    String get();

    // 靜態(tài)方法(新特性)
    static String bar() {
        return "haha";
    }
  
    // default修飾的實例方法(新特性)
    default String hello() {
        return "hello";
    }
}

這樣一來恶耽,有點類似于多繼承了密任,但是可能會有沖突:

  • 類優(yōu)先原則
  • 實現(xiàn)的多個接口中的方法若有沖突,只能實現(xiàn)一個偷俭,其他的必須舍棄
public class InterfaceTest {

    static interface Walkable {
        default void walk() {
            System.out.println("walk() from Walkable");
        }
    }

    static interface Speekable {
        default void speek() {
            System.out.println("walk() from Walkable");
        }

        default void walk() {
            System.out.println("walk() from Walkable");
        }
    }

    static class Dog implements Walkable, Speekable {

        @Override
        public void walk() {
            // 1. 只能選擇多個同名default方法中的一個來實現(xiàn),其余的必須舍棄
            Speekable.super.walk();
        }
    }

    static class Animal {
        public void walk() {
            System.out.println("walk() from Animal");
        }
    }

    static class Cat extends Animal implements Walkable {
    }

    public static void main(String[] args) {
        Cat cat = new Cat();
        // 2. 類優(yōu)先原則,此處的walk()來自于父類Animal,而不是接口Walkable
        cat.walk(); // walk() from Animal
    }
}

4 可重復的注解

在jdk1.8之前,java中的注解不能直接重復出現(xiàn)在同一個被他修飾的方法或?qū)傩陨侠嘶洹V荒芡ㄟ^數(shù)組或者其他方式來變向的實現(xiàn)這個需求。

在jdk1.8里,可以讓注解在同一個被修飾的方法或?qū)傩陨现貜统霈F(xiàn)涌萤。


public class AnnotationTest {

    @Target({ ElementType.METHOD })
    @Retention(RetentionPolicy.RUNTIME)
    @Repeatable(Roles.class)
    public static @interface Role {
        String value();
    }

    @Target({ ElementType.METHOD })
    @Retention(RetentionPolicy.RUNTIME)
    public static @interface Roles {
        Role[] value();
    }

    public static class RepeatableAnnotationTest {

        @Role("admin")
        @Role("user")
        public void doProcess() {
        }
    }

    public static void main(String[] args) throws Exception {
        RepeatableAnnotationTest obj = new RepeatableAnnotationTest();

        Method method = obj.getClass().getDeclaredMethod("doProcess");

        Role[] annotations = method.getAnnotationsByType(Role.class);

        // @cn.xxx$Role(value=admin)
        // @cn.xxx$Role(value=user)
        Arrays.stream(annotations).forEach(System.out::println);
    }
}

5 JavaScript引擎

public static void main(String[] args) throws ScriptException {
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine engine = manager.getEngineByName("JavaScript");
    Object ret = engine.eval("function add(i,j){return i+j;} add(1,1);");
    
    //out: 2.0
    System.out.println("out: " + ret);
}

6 JVM內(nèi)存模型變化

永久帶被移除,引入了Metaspace淹遵。

詳情可參看: http://blog.csdn.net/hylexus/article/details/53771460

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市负溪,隨后出現(xiàn)的幾起案子透揣,更是在濱河造成了極大的恐慌,老刑警劉巖川抡,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辐真,死亡現(xiàn)場離奇詭異,居然都是意外死亡崖堤,警方通過查閱死者的電腦和手機侍咱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來密幔,“玉大人楔脯,你說我怎么就攤上這事】杷Γ” “怎么了昧廷?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長偎箫。 經(jīng)常有香客問我木柬,道長,這世上最難降的妖魔是什么镜廉? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任弄诲,我火速辦了婚禮愚战,結(jié)果婚禮上娇唯,老公的妹妹穿的比我還像新娘。我一直安慰自己寂玲,他們只是感情好塔插,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著拓哟,像睡著了一般想许。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天流纹,我揣著相機與錄音糜烹,去河邊找鬼。 笑死漱凝,一個胖子當著我的面吹牛疮蹦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播茸炒,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼愕乎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了壁公?” 一聲冷哼從身側(cè)響起感论,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎紊册,沒想到半個月后比肄,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡囊陡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年薪前,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片关斜。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡示括,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出痢畜,到底是詐尸還是另有隱情垛膝,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布丁稀,位于F島的核電站吼拥,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏线衫。R本人自食惡果不足惜凿可,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望授账。 院中可真熱鬧枯跑,春花似錦、人聲如沸白热。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽屋确。三九已至纳击,卻和暖如春续扔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背焕数。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工纱昧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人堡赔。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓砌些,卻偏偏與公主長得像,于是被迫代替她去往敵國和親加匈。 傳聞我的和親對象是個殘疾皇子存璃,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)雕拼,斷路器纵东,智...
    卡卡羅2017閱讀 134,651評論 18 139
  • Java8 in action 沒有共享的可變數(shù)據(jù),將方法和函數(shù)即代碼傳遞給其他方法的能力就是我們平常所說的函數(shù)式...
    鐵牛很鐵閱讀 1,229評論 1 2
  • 為大家分享一篇介紹java8新特性的文章. 身為一名Java程序員啥寇,大家可能都有這樣的經(jīng)歷:調(diào)用一個方法得到了返回...
    H_Man閱讀 2,585評論 0 5
  • 上一篇博客中Java8函數(shù)式編程之三:函數(shù)式接口 - 簡書留下的問題是關于Consumer接口的偎球,本篇博客就來介紹...
    linkinparkzlz閱讀 1,425評論 0 0
  • 幾年前就一直聽說“不忘初心”衰絮,今天才知道真正內(nèi)涵。 前幾日閑來無事拿起刻刀磷醋,才想起自己許久不曾刻過章了猫牡。于是便找好...
    半榛半檸閱讀 2,417評論 5 75