Java8 已經發布好久,是自 java5(2004年發佈)以後 Oracle 發佈的最重要的一個版本。其中包括語言、編譯器、庫、工具和 JVM 等諸多方面的新特性,對於國內外互聯網公司來講,Java8 是之後技術開發的趨勢。這裏主要講解在開發中幾個核心的新特性。(主要重新特性概念解釋、語法定義、簡單代碼演示、優缺點分析、項目實戰幾個方面編寫)。java
在註冊網站時,咱們會在註冊後使用網站提供的默認頭像,應用程序安裝成功後一般會提供默認圖標,在電商網站購買過商品進行支付時,咱們會設置經常使用收貨地址爲默認地址,看起來生活中不少場景都有默認一說。Java8 開始,一樣也有默認這個詞的出現,這裏針對接口 Java8 擴展了接口原有功能,並對默認方法提供支持。 編程
從 Java8 開始,程序容許在接口中包含帶有具體實現的方法,使用 default 修飾,這類方法就是默認方法。默認方法在接口中能夠添加多個,而且 Java8 提供了不少對應的接口默認方法。框架
Java8 中接口能夠包含實現方法,須要使用 default 修飾,此類方法稱爲默認方法。默認方法在接口中必須提供實現,在實現類中能夠按需重寫。默認方法只能在實現類中或經過實現類對象調用。以下形式:ide
public interface IMathOperation { /** * 定義接口默認方法 支持方法形參 */ default void print(){ System.out.println("數值運算基本接口默認打印方法。。。"); } }
定義 IMathOperation 接口並提供默認打印方法函數
public interface IMathOperation { /** * 定義接口默認方法 支持方法形參 */ default void print(){ System.out.println("這是數值運算基本接口。。。"); } /** * 整數加法運算方法 * @param a * @param b * @return */ public int add(int a,int b); }
定義 MathOperationImpl 子類實現 IMathOperation 接口工具
子類在實現時,按需重寫接口默認方法測試
public class MathOperationImpl implements IMathOperation { @Override public int add(int a, int b) { // 子類中能夠直接調用父類接口默認方法 IMathOperation.super.print(); // 調用父類靜態默認方法 IMathOperation.version(); return a+b; } }
使用 Java8 開發應用程序,子類實現多個接口時,對於接口默認方法定義容許定義多個默認方法,而且接口默認方法可能會出現同名狀況,此時對於子類在實現或者調用時一般遵循如下原則:網站
1.類中的方法優先級最高code
2.若是第一條沒法進行判斷,那麼子接口的優先級更高:函數簽名相同時,優先選擇擁有最具體實現的默認方法的接口,即若是B繼承了A,那麼B就比A更加具體對象
示例代碼以下:
/** * 定義手機接口 提供默認info方法 */ public interface Phone { default void info(){ System.out.println("這是一部手機"); } } /** * 定義MiPhone子接口 並繼承 Phone 父接口 同時也提供info方法 */ public interface MiPhone extends Phone{ default void info(){ System.out.println("這是一部小米手機"); } } /** * 實現 Phone MiPhone 接口 */ public class M2sPhone implements Phone,MiPhone { public static void main(String[] args) { new M2sPhone().info(); } } 打印結果: 這是一部小米手機
接口中除了容許定義多個默認方法以外,Java8 也容許在接口中定義多個靜態方法,靜態方法即經過 static 修飾的方法。接口中靜態方法也必須提供實現,提供了能夠直接經過接口調用方法的方式。
public interface IMathOperation { /** * 定義接口默認方法 支持方法形參 */ default void print(){ System.out.println("這是數值運算基本接口。。。"); } /** * 定義靜態默認方法 */ static void version(){ System.out.println("這是1.0版簡易計算器"); } }
接口中的靜態方法只能經過接口自己去調用,相似於 Class 中的靜態方法,不存在默認方法中的多繼承問題,靜態方法並不能在實現類中被覆寫,實現類中能夠聲明相同的方法,但這兩個方法之間除了名字相同,並無 Override 關係。
這裏以博客網站舉例,好比統計每月網站前三活躍用戶(按用戶文章發表量評判),使用集合遍歷操做來使用接口默認方法,對於測試數據以下:
uList= new ArrayList<>(); uList.add(new UserDto(35,"zs","126xxx@126.com",800,"lv4")); uList.add(new UserDto(60,"js_li","157xxx@139.com",500,"lv3")); uList.add(new UserDto(78,"fc_007","126@126.com",260,"lv2"));
獲得統計集合數據後,最簡單的方式使用加強 for 實現,也是 java8 以前經常使用的方式。
System.out.println("----------集合遍歷-->原始遍歷方法---------"); for(UserDto u:uList){ System.out.println(u); }
/** * @Version 1.0 * 定義MyList 接口 並提供myForeach 默認方法 */ public interface MyList<T> { /** * 定義接口默認方法 * @param t */ default public void myForeach(List<T> t){ for(Object o:t){ System.out.println(o); } } } /** * @Version 1.0 * 定義MyArrayList 子類 實現MyList 接口,繼承ArrayList */ public class MyArrayList<T> extends ArrayList<T> implements MyList<T> { } /** 執行遍歷 */ System.out.println("----------集合遍歷-->自定義接口默認方法---------"); // 使用自定義的接口默認方法實現集合元素遍歷 uList.myForeach(uList);
System.out.println("----------集合遍歷-->加強的List接口默認方法---------"); uList.forEach(new Consumer<UserDto>() { @Override public void accept(UserDto userDto) { System.out.println(userDto); } }); }
這裏以博客網站舉例,好比統計每月網站前三活躍用戶(按用戶文章發表量評判),使用集合排序操做來使用接口默認方法,對於測試數據以下:
System.out.println("--------Collections.sort 實現按文章發表量排序---------"); Collections.sort(uList, new Comparator<UserDto>() { @Override public int compare(UserDto o1, UserDto o2) { return o1.getTotal()-o2.getTotal(); } }); uList.forEach(System.out::println);
藉助 Java8 加強的 List 接口默認 Sort 方法實現集合排序操做
System.out.println("--------集合默認sort方法實現按文章發表量排序---------"); uList.sort(new Comparator<UserDto>() { @Override public int compare(UserDto o1, UserDto o2) { return o1.getTotal()-o2.getTotal(); } }); uList.forEach(System.out::println);
Stream 流提供了針對集合的多種操做,這裏藉助 Stream 的 sorted 實現集合元素排序操做,後續會對 Stream 作詳細介紹。
System.out.println("--------Stream實現按文章發表量排序---------"); List<UserDto> result= uList.stream().sorted(new Comparator<UserDto>() { @Override public int compare(UserDto o1, UserDto o2) { return o1.getTotal()-o2.getTotal(); } }).collect(Collectors.toList()); result.forEach(System.out::println);
一、接口的兼容性獲得解決
使用接口編程的好處是,開發是面向抽象而再也不是面向具體來編程,使得程序變得很靈活,缺陷是,當須要修改接口時候,此時對應實現該接口的類須要所有修改,舉個例子, java 8 以前對於咱們經常使用的集合框架沒有 foreach 方法,一般能想到的解決辦法是在 JDK 裏給相關的接口添加新的方法及實現。從 Java8 開始,引入了接口默認方法,這樣的好處也是很明顯的,首先解決了 Java8 之前版本接口兼容性問題,同時對於咱們之後的程序開發,也能夠在接口子類中直接使用接口默認方法,而再也不須要再各個子類中各自實現響應接口方法。
二、子類在實現接口方法時靈活度更高
子類在實現接口時,能夠按需重寫,再也不向 Java8 之前接口方法必須所有實現,同時接口默認方法能夠在子類中直接進行調用,靈活度比較高。
三、開發中避免大量工具類建立
接口中引入靜態方法,對於原有項目開發中出現大量的工具類大量靜態方法的代碼即可以遷移到接口中定義與實現,省去大量工具類的建立。
四、提高了對Lambda表達式的支持
Lambda 是針對只有一個抽象方法的接口來講的,接口中引入接口默認方法與靜態方法,在對接口這些方法進行調用時,能夠引入 Lambda 表達式簡化了原有代碼的書寫形式,使得代碼變得更加簡潔。