Android Java 8 支持

前言

在Kotlin流行的當(dāng)下,談?wù)?Java 8 或許有點(diǎn)逆潮流。然現(xiàn)代編程語(yǔ)言發(fā)展過(guò)程中有一些共性的東西,談?wù)効赡芤灿兄谙嗷ソ梃b。
Android Gradle 插件 4.0.0 以前,Android 對(duì) Java 8 的支持并不好,對(duì)于函數(shù)式密切相關(guān)的Stream 的支持受限于平臺(tái)版本,使得對(duì)Java 8的使用僅僅停留在 Lambda 表達(dá)式。Gradle 插件 4.0.0 之后,官方通過(guò) desugar 的引入跨越了平臺(tái)版本限制,對(duì) Java 8 有了更多實(shí)際的支持。本文介紹 Android Java 8 基本配置及概念,同時(shí)用一個(gè)例子展示了 Java 8 常用特性。

關(guān)于脫糖(desugar)

通過(guò) desugar 字節(jié)碼轉(zhuǎn)換實(shí)現(xiàn) Java 8 語(yǔ)言功能支持

如圖所示,Android Java代碼編譯過(guò)程如下

  1. 通過(guò)JDK編譯生成通用中間碼.class文件
  2. 通過(guò)R8混淆,D8編譯成可被Android虛擬機(jī)執(zhí)行的Dex文件

在沒(méi)有desugar之前,高版本的.class文件中部分特性字節(jié)碼無(wú)法被D8識(shí)別轉(zhuǎn)化,通過(guò)desugar轉(zhuǎn)化這部分字節(jié)碼。

概念說(shuō)明

  • D8:Java后端編譯器,將class文件編譯成Android可執(zhí)行dex文件。
  • R8:混淆工具ProGuard代替工具,用于代碼的壓縮(shrinking)和混淆(obfuscation)。
  • 脫糖(desuger):集成于D8內(nèi),通過(guò)字節(jié)碼轉(zhuǎn)化支持 Java 高版本語(yǔ)言特性。

開(kāi)啟 Java 8 支持配置

android {
  defaultConfig {
    // Required when setting minSdkVersion to 20 or lower
    multiDexEnabled true
  }

  compileOptions {
    // Flag to enable support for the new language APIs
    coreLibraryDesugaringEnabled true
    // Sets Java compatibility to Java 8
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

dependencies {
  coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.9'
}

常用特性介紹

Lambda 表達(dá)式

Lambda簡(jiǎn)化了單方法接口匿名類的代碼呈現(xiàn)。這些接口,一般具有test、mapper、merge、block等函數(shù)式操作語(yǔ)義。
假設(shè)存在一個(gè)如下數(shù)據(jù)類

class Person {
    public int age;
    public String name;

    public Person() {
    }

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }
}

在使用Java 6開(kāi)發(fā)時(shí)候常會(huì)出現(xiàn)如下類似代碼

public List<Person> filter(List<Person> list) {
    ArrayList<Person> result = new ArrayList<>();
    for (Person person : list) {
        if (person.age > 0 && person.name != null) {
            result.add(person);
        }
    }
    return result;
}

如果要支持過(guò)濾條件可定義,會(huì)構(gòu)建如下形式代碼

interface Checker {
    boolean check(Person person);
}

public List<Person> filter(List<Person> list, Checker checker) {
    List<Person> result = new ArrayList<>();
    for (Person person : list) {
        if (checker.check(person)) {
            result.add(person);
        }
    }
    return result;
}

// call place
List<Person> filterPersonList = filter(personList, new Checker() {
    @Override
    public boolean check(Person person) {
        return person.age > 0 && person.name != null;
    }
});

使用Lambda替換 call place 位置代碼,結(jié)果如下

// call place
List<Person> filterPersonList = filter(personList, person -> person.age > 0 && person.name != null);

方法引用

Lambda的擴(kuò)展,可以使用本地方法替代Lambda中的箭頭表達(dá)式
對(duì)于上述例子中的call place能進(jìn)一步更改為如下代碼

private boolean localChecker(Person person) {
    return person.age > 0 && person.name != null;
}

// call place
List<Person> filterPersonList = filter(personList, this::localChecker);

Stream

Stream對(duì)Collection接口封裝了一系列函數(shù)方法,支持鏈?zhǔn)秸{(diào)用,上例可進(jìn)一步更改為

List<Person> filterPersonList = personList.stream()
        .filter(this::localChecker)
        .collect(Collectors.toCollection(ArrayList::new));

一般情況下過(guò)濾獲取目標(biāo)不是最終意圖,最終意圖可能是數(shù)據(jù)轉(zhuǎn)換,可能是聚合操作,使用stream能很好的進(jìn)行這些操作

// 聚合
personList.stream()
        .filter(this::localChecker)
        .count();

// 轉(zhuǎn)換后操作
personList.stream()
        .filter(this::localChecker)
        .map(p -> p.name)
        .sorted();

默認(rèn)和靜態(tài)接口方法

支持接口方法默認(rèn)實(shí)現(xiàn),能規(guī)避新增接口方法時(shí)同時(shí)更改多個(gè)實(shí)現(xiàn)類的情況。源碼中stream實(shí)現(xiàn)即依賴default擴(kuò)展了Collection接口

// Collections.java
default Stream<E> stream() {
    return StreamSupport.stream(spliterator(), false);
}

Optional

Optional用于對(duì)空值處理,相較于Kotlin語(yǔ)法級(jí)別的支持,Optional以類形式的封裝支持略顯不夠優(yōu)雅,當(dāng)相較于通過(guò)規(guī)范約定,注解標(biāo)識(shí)的方式,也算是提供了一個(gè)更不容易出錯(cuò)的方式。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容