更新時間:2020-09-11 15:28:59 來源:動力節(jié)點 瀏覽998次
一、接口的默認方法
Java 8允許我們給接口添加一個非抽象的方法實現(xiàn),只需要使用defau·t關鍵字即可,這個特征又叫做擴展方法,示例如下:
interface Formula { double calculate(int a); default double sqrt(int a) { return Math.sqrt(a); }}
Formula接口在擁有calculate方法之外同時還定義了sqrt方法,實現(xiàn)了Formula接口的子類只需要實現(xiàn)一個calculate方法,默認方法sqrt將在子類上可以直接使用。
Formula formula = new Formula() { @Override public double calculate(int a) { return sqrt(a * 100); }};formula.calculate(100); // 100.0formula.sqrt(16); // 4.0
文中的formula被實現(xiàn)為一個匿名類的實例,該代碼非常容易理解,6行代碼實現(xiàn)了計算 sqrt(a * 100)。在下一節(jié)中,我們將會看到實現(xiàn)單方法接口的更簡單的做法。
譯者注: 在Java中只有單繼承,如果要讓一個類賦予新的特性,通常是使用接口來實現(xiàn),在C++中支持多繼承,允許一個子類同時具有多個父類的接口與功能,在其他語言中,讓一個類同時具有其他的可復用代碼的方法叫做mixin。新的Java 8 的這個特新在編譯器實現(xiàn)的角度上來說更加接近Scala的trait。 在C#中也有名為擴展方法的概念,允許給已存在的類型擴展方法,和Java 8的這個在語義上有差別。
首先看看在老版本的Java中是如何排列字符串的:
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 傳入一個List對象以及一個比較器來按指定順序排列。通常做法都是創(chuàng)建一個匿名的比較器對象然后將其傳遞給sort方法。
在Java 8 中你就沒必要使用這種傳統(tǒng)的匿名對象的方式了,Java 8提供了更簡潔的語法,lambda表達式:
Collections.sort(names, (String a, String b) -> { return b.compareTo(a);});
看到了吧,代碼變得更段且更具有可讀性,但是實際上還可以寫得更短:
Collections.sort(names, (String a, String b) -> b.compareTo(a));
對于函數(shù)體只有一行代碼的,你可以去掉大括號{}以及return關鍵字,但是你還可以寫得更短點:
Collections.sort(names, (a, b) -> b.compareTo(a));
Java編譯器可以自動推導出參數(shù)類型,所以你可以不用再寫一次類型。接下來我們看看lambda表達式還能作出什么更方便的東西來
Lambda表達式是如何在java的類型系統(tǒng)中表示的呢?每一個·ambda表達式都對應一個類型,通常是接口類型。而“函數(shù)式接口”是指僅僅只包含一個抽象方法的接口,每一個該類型的·ambda表達式都會被匹配到這個抽象方法。因為默認方法不算抽象方法,所以你也可以給你的函數(shù)式接口添加默認方法。
我們可以將·ambda表達式當作任意只包含一個抽象方法的接口類型,確保你的接口一定達到這個要求,你只需要給你的接口添加 Functiona·Interface注解,編譯器如果發(fā)現(xiàn)你標注了這個注解的接口有多于一個抽象方法的時候會報錯的。
@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如果沒有指定,上面的代碼也是對的。
譯者注 將lambda表達式映射到一個單方法的接口上,這種做法在Java 8之前就有別的語言實現(xiàn),比如Rhino JavaScript解釋器,如果一個函數(shù)參數(shù)接收一個單方法的接口而你傳遞的是一個function,Rhino 解釋器會自動做一個單接口的實例到function的適配器,典型的應用場景有 org.w3c.dom.events.EventTarget 的addEventListener 第二個參數(shù) EventListener。
四、方法與構造函數(shù)引用
前一節(jié)中的代碼還可以通過靜態(tài)方法引用來表示:
Converter<String, Integer> converter = Integer::valueOf;
Integer converted = converter.convert("123");System.out.println(converted); // 123
Java 8 允許你使用 :: 關鍵字來傳遞方法或者構造函數(shù)引用,上面的代碼展示了如何引用一個靜態(tài)方法,我們也可以引用一個對象的方法:
converter = something::startsWith;
String converted = converter.convert("Java");System.out.println(converted); // "J"
接下來看看構造函數(shù)是如何使用::關鍵字來引用的,首先我們定義一個包含多個構造函數(shù)的簡單類:
class Person {
String firstName; String lastName; Person() {} Person(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; }}
接下來我們指定一個用來創(chuàng)建Person對象的對象工廠接口:
interface PersonFactory<P extends Person> {
P create(String firstName, String lastName);}
這里我們使用構造函數(shù)引用來將他們關聯(lián)起來,而不是實現(xiàn)一個完整的工廠:
PersonFactory<Person> personFactory = Person::new;
Person person = personFactory.create("Peter", "Parker");
我們只需要使用 Person::new 來獲取Person類構造函數(shù)的引用,Java編譯器會自動根據(jù)PersonFactory.create方法的簽名來選擇合適的構造函數(shù)。
以上就是動力節(jié)點java培訓機構的小編針對“Java8新特性以及原因,入門學習”的內(nèi)容進行的回答,希望對大家有所幫助,如有疑問,請在線咨詢,有專業(yè)老師隨時為你服務。