JDK8特性深刻學習筆記-Optional和方法引用(3)

Optional

Optional是一個獨立的類型,在實際應用中,主要是爲了解決NullPointerExceptionjava

基於值的類

Optional類爲 終態類(class 前有 final修飾)
Optional是 基於值的類(Value-based Classes)(還有LocalDateTime),對於基於值的類有如下特色
  • 是final不可變的(可是有可能存在可變對象的引用)
  • 有hashcode和toString的實現,可是這些實現僅僅是根據實例自己的狀態,不會依賴於其餘的變量
  • 不會使用身份敏感的操做例如「==」 ,或者hashcode或者鎖等。
  • 僅僅依靠equals方法來判斷相等性
  • 不會擁有可訪問的構造方法,經過工廠方法來建立的,工廠方法並不保證明例的一致性
  • 當相等時是能夠任意替換的。

Optional的構造方法

  • empty():構造一個容器內容爲空的Optional
  • of():直接new一個內容爲T的Optional,調用者需確保T不能爲空,不然拋出空指針異常。
  • ofNullable():構造一個可能爲null也可能不爲null的對象,若是T爲null,則調用empty,不然調用of

Optional的基本使用

Optional<String> optional = Optional.of("hello");
// 面向對象風格的寫法(不推薦)
if(optional.isPresent()){
    System.out.println(optional.get())
}

// 經過函數式風格
optional.ifPresent(i -> System.out.println(optional.get()));

若是不在optional.get()方法外不使用isPresent,idea會提示警告,若是Optional的內容爲空,get方法會拋出異常。ide

orElse(T)

optional.orElse("T");

若是內容爲空,則將內容指定爲T,不然不作任何的改變。函數

避免集合的空判斷

Person person = new Person();
List<String> strings = new ArrayList<>();
person.setList(strings);
Optional.ofNullable(person).map(item -> item.getList()).orElse(Collections.emptyList());

Optional做爲方法參數

public void test(Optional optional){

}

此時idea會提示警告,Optional是沒有序列化的,不要做爲變量傳入,應該使用函數式的方式來傳入。this

方法引用(method reference)

在何時能夠使用方法引用: 僅僅當lambda表達式裏的實現能剛好被一個方法引用所表示,可是不少狀況下lambda內容是較爲複雜的。因此方法引用算是Lambda表達式的一個語法糖。idea

方法引用的簡單使用

List<String> list = Arrays.asList("1", "2", "3");

list.forEach(System.out::println)

咱們能夠將方法引用看做是一個函數指針(function pointer)(C中的概念,將指針指向一個函數)。
方法引用的要求:你所實現的lambda方法體,剛好有一個方法完成一樣的事情:一樣的參數和返回值,一樣的功能邏輯。指針

方法引用共分爲4類:code

  • 類名::靜態方法
  • 引用名::實例方法名
  • 類目::實例方法名
  • 構造方法引用,類名::new

其中類目::實例方法名這個並不容易理解,例如對象

public class Person {
    private Integer age;
    private String name;

    public int compareName(Person person){
        return this.name.compareToIgnoreCase(person.getName());
    }
}

public class Test {
    public static void main(String[] args) {
        Person person1 = new Person();
        person1.setName("abc");
        Person person2 = new Person();
        person2.setName("zdf");
        List<Person> list = Arrays.asList(person1, person2);
        list.sort(Person::compareName);
        list.forEach(i -> System.out.println(i.getName()));
    }
}

sort方法接受的是兩個參數的Consumer,而comaperName方法只有一個入參,可是方法引用成功。緣由是這個CompareName是在Person類中實現的方法,其中的一個比較對象是這個方法的一個屬性,因此默認Consumer的第一個參數即爲這個類自己接口

默認方法

interface MyInterface1{
    default void myMethod(){
        System.out.println("1");
    }
}
interface MyInterface2{
    default void myMethod(){
        System.out.println("2");
    }
}

public class MyClass implements MyInterface1, MyInterface2{

    @Override
    public void myMethod(){
        MyInterface2.super.myMethod();
    }
}

接口中已經支持了默認方法實現。可是若是同時實現兩個同名默認方法實現,編譯器由於不知道到底使用哪個,而會報錯。這時候,必須使用重寫myMethod方法,顯式的告訴編譯器須要選擇哪一個具體方法實現。get

public class MyImpl1 implements MyInterface1 {
    @Override
    public void myMethod() {
        System.out.println("aa");
    }
}

public class MyClass extends MyImpl1 implements MyInterface2{
    public static void main(String[] args) {
        MyClass myClass = new MyClass();
        myClass.myMethod();
    }
}

java認爲實現類的優先級大於default默認方法的優先級,因此上面代碼將打印aa。

相關文章
相關標籤/搜索