Java8極簡(jiǎn)手冊(cè)-01

為忙碌的程序員歸納總結(jié)和翻譯的Java8極簡(jiǎn)教程,有助于快速了解Java8的新特性。

系列文章鏈接:

Java8極簡(jiǎn)手冊(cè)-01
Java8極簡(jiǎn)手冊(cè)-02
Java8極簡(jiǎn)手冊(cè)-03
Java8極簡(jiǎn)手冊(cè)-04

接口的默認(rèn)方法(Default Methods for Interfaces)

Java 8允許我們利用default關(guān)鍵字在接口中定義非抽象的方法實(shí)現(xiàn),這個(gè)功能也被稱為虛擬擴(kuò)展方法( virtual extension methods)。

以下是第一個(gè)例子:

interface Formula {
    double calculate(int a);

    default double sqrt(int a) {
        return Math.sqrt(a);
    }
}

除了抽象方法(可以理解為無(wú)具體實(shí)現(xiàn)的方法) calculate之外,接口 Formula 里面還定了一個(gè)默認(rèn)方法 sqrt。在具體的實(shí)現(xiàn)類里面,抽象方法 calculate需要被重新>實(shí)現(xiàn),而默認(rèn)方法sqrt則可以被實(shí)現(xiàn)類直接使用。

Formula formula = new Formula() {
    @Override
    public double calculate(int a) {
        return sqrt(a * 100);
    }
};

formula.calculate(100);     // 100.0
formula.sqrt(16);           // 4.0

該公式是作為匿名對(duì)象實(shí)現(xiàn)的,代碼或許過(guò)于冗長(zhǎng):6行代碼實(shí)現(xiàn)的僅僅是一個(gè)簡(jiǎn)單的計(jì)算 sqrt(a * 100),下一節(jié)我們將看到在Java8中是怎么樣更優(yōu)雅地實(shí)現(xiàn)這樣的單方法對(duì)象的。

Lambda表達(dá)式

讓我們從一個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明如何在以前版本的Java中對(duì)字符串列表進(jìn)行排序:

List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");

Collections.sort(names, new Comparator<String>() {
    @Override
    public int compare(String a, String b) {
        return b.compareTo(a);
    }
});

靜態(tài)方法Collections.sort接受一個(gè)list和一個(gè)comparator,以便對(duì)給定list的元素進(jìn)行排序。 很多時(shí)候我們會(huì)發(fā)現(xiàn)需要先創(chuàng)建匿名comparator,并將它們傳遞給排序方法。

從Java 8開(kāi)始,我們不需要整天創(chuàng)建匿名對(duì)象了,而是可以使用更短的語(yǔ)法 :lambda expressions(lambda表達(dá)式):

Collections.sort(names, (String a, String b) -> {
    return b.compareTo(a);
});

你可以看見(jiàn),代碼更精簡(jiǎn),而且更具可讀性了(注:可讀性是對(duì)于熟悉lambda的開(kāi)發(fā)者來(lái)說(shuō)的),而且,我們還可以把代碼寫(xiě)的更精簡(jiǎn):

Collections.sort(names, (String a, String b) -> b.compareTo(a));

對(duì)于一行方法體,您可以跳過(guò)大括號(hào){}return關(guān)鍵字, 所以還可以把它變得更短:

names.sort((a, b) -> b.compareTo(a));

列表現(xiàn)在有了一個(gè)排序方法。 此外,java編譯器會(huì)知道參數(shù)類型,所以你可以跳過(guò)它們。 讓我們深入了解如何在更多的場(chǎng)景中使用lambda表達(dá)式。

函數(shù)式接口(Functional Interfaces)

Lambda表達(dá)式如何匹配識(shí)別Java的類型系統(tǒng)?

每個(gè)lambda對(duì)應(yīng)于由接口指定的給定類型,一個(gè)所謂的函數(shù)式接口必須包含一個(gè)精確的抽象方法聲明,該類型的每個(gè)lambda表達(dá)式都將與此抽象方法匹配。 由于默認(rèn)方法不
是抽象的,你可以自由地將默認(rèn)方法添加到你的函數(shù)式接口。

只要接口滿足只包含一個(gè)抽象方法的約定,我們就可以使用任意接口作為lambda表達(dá)式。 為了確保你的接口符合要求,你應(yīng)該添加@FunctionalInterface注解。 編譯器知道這>個(gè)注釋,并會(huì)在你嘗試向接口添加第二個(gè)抽象方法聲明后立即拋出編譯器錯(cuò)誤。

例子:

@FunctionalInterface
interface Converter<F, T> {
    T convert(F from);
}
Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
Integer converted = converter.convert("123");
System.out.println(converted);    // 123

需要注意的是,如果@FunctionalInterface注釋被省略掉,代碼也是有效的。

方法和構(gòu)造器引用

The above example code can be further simplified by utilizing static method references:

上面的示例代碼可以通過(guò)使用靜態(tài)方法引用進(jìn)一步簡(jiǎn)化:

Converter<String, Integer> converter = Integer::valueOf;
Integer converted = converter.convert("123");
System.out.println(converted);   // 123

Java 8讓您能夠通過(guò)::關(guān)鍵字傳遞方法或構(gòu)造函數(shù)的引用。 上面的例子展示了如何引用一個(gè)靜態(tài)方法。 但是我們也可以引用對(duì)象的方法:

class Something {
    String startsWith(String s) {
        return String.valueOf(s.charAt(0));
    }
}
Something something = new Something();
Converter<String, String> converter = something::startsWith;
String converted = converter.convert("Java");
System.out.println(converted);    // "J"

Let's see how the :: keyword works for constructors. First we define an example class with different constructors:

我們來(lái)看看::關(guān)鍵字如何用于構(gòu)造函數(shù),首先我們用不同的構(gòu)造函數(shù)定義一個(gè)示例類:

class Person {
    String firstName;
    String lastName;

    Person() {}

    Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

接下來(lái),我們指定一個(gè)用于創(chuàng)建新的人員的Person工廠接口:

interface PersonFactory<P extends Person> {
    P create(String firstName, String lastName);
}

我們不是手動(dòng)實(shí)現(xiàn)工廠,而是通過(guò)構(gòu)造函數(shù)引用將所有東西粘合在一起:

PersonFactory<Person> personFactory = Person::new;
Person person = personFactory.create("Peter", "Parker");

我們通過(guò)Person :: new創(chuàng)建一個(gè)對(duì)Person構(gòu)造函數(shù)的引用。 Java編譯器通過(guò)匹配PersonFactory.create的參數(shù)和類型自動(dòng)選擇正確的構(gòu)造函數(shù)。

?著作權(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)容