今天我來聊聊 Java8 的一些新的特性,確實 Java8 的新特性的出現,給開發者帶來了很是大的便利,可能剛剛開始的時候會有點不習慣的這種寫法,可是,當你真正的熟悉了以後,你必定會愛上這些新的特性的,這篇文章就來聊聊這些新特性。編程
lambda 表達式在項目中也是用到了,這種新的語法的加入,對於使用 Java 多年的我,我以爲是如虎添翼的感受哈,這種新的語法,大大的改善了之前的 Java 的代碼,變得更加的簡潔,我以爲這也是爲何 Java8 可以很快的流行起來的緣由吧。多線程
這裏咱們用幾個之前的經典的 Java 的寫法和用 lambda 表達式的方式進行對比。ide
線程的用法函數式編程
原始的線程用法函數
//使用匿名內部類的方式啓動多線程 new Thread(new Runnable() { @Override public void run() { System.out.println("這是使用匿名內部類的方式。。。"); } }).start();
lambda 表達式測試
//使用lambda表達式方式 new Thread(() -> { System.out.println("這是使用lambda表達式的方式。。。"); }).start();
你會發現,用 lambda 表達式的方式可以寫更少的代碼,看起來也會更加的舒服和簡潔。線程
這裏沒有使用參數,只是一個簡單的例子。code
咱們再看一個例子。對象
遍歷方式繼承
原始方式
//原始方式 List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); for (int i : list) { System.out.println(i); }
lambda 表達式方式
//使用lambda表達式代替foreach循環 Stream.of(1, 2, 3, 4, 5).forEach((x) -> { System.out.println(x); });
在原始的方式中,咱們通常使用 foreach 的方式進行遍歷,有了 Java8 的方式以後,咱們能夠用 forEach
方法,而後,再用 lambda 表達式的方式進行遍歷,也讓原來的方式變得更加的簡潔。
在這個例子中,咱們加了一個參數,在()
中間咱們加了一個 x
,表明的意思實際上是:經過 forEach
方法,咱們把一個元素已經賦值到 x
中了,拿到這個 x
,咱們就能夠輸出結果。
總結
lambda 的使用方式其實很簡單,能夠總結爲下面的方法。
([參數可選,...]) -> { }
方法引用實際上是 lambda 表達式的部分的簡化,也就是爲了簡化 lambda 表達式而存在的感受,下面咱們還講講怎麼使用方法引用。
/** * @return void * @Author ouyangsihai * @Description 方法引用測試 * @Date 10:23 2019/5/14 * @Param [] **/ @Test public void test_method_reference() { //使用lambda表達式 Stream.of("A", "BB", "CCC", "DDDD", "FFFFF") .map(s -> s.length()) //lambda .forEach((x) -> { System.out.println(x); }); //使用靜態方法引用 Stream.of("A", "BB", "CCC", "DDDD", "FFFFF") .map(String::length) //靜態方法引用 .forEach((x) -> { System.out.println(x); }); //使用實例方法引用 Stream.of( new ClassMate("1", "歐陽思海"), new ClassMate("2", "sihai") ).map(ClassMate::getName)//實例方法引用 .forEach(x -> { System.out.println(x); }); }
在第一個測試中,咱們用的是 lambda 表達式來獲取每一個字符串的長度。
s -> s.length()
在第二個測試中,咱們使用的是靜態方法引用來獲取每一個字符串的長度。
String::length
在第三個測試中,咱們使用的是實例方法引用。
ClassMate::getName
解釋
① map 方法是映射的意思。
② forEach 方式是遍歷每個元素。
③ ClassMate 是一個包含 id 和 name 的簡單 po 類。
經過上面這個例子,基本上咱們就知道怎麼使用方法引用了。下面咱們進行一個小的總結。
總結
① 使用方法
類名::方法名
② 方法能夠是:靜態方法,實例方法
在上面咱們講了方法引用的基本使用方法,其實除了方法引用之外,還有構造函數引用,回想一下,之前咱們建立對象是怎麼作?是否是須要 new 一個對象呢,那麼如今用構造函數引用又是怎麼作的呢?
下面咱們用一個例子講解一下,在這個例子中,對象仍是使用上面的 ClassMate
。
/** * @return void * @Author ouyangsihai * @Description 構造函數引用測試 * @Date 10:23 2019/5/14 * @Param [] **/ @Test public void test_method_reference2() { //使用lambda表達式 Stream.of("A", "BB", "CCC", "DDDD", "FFFFF") .map(s -> new ClassMate(s)) //lambda .collect(Collectors.toList()); //使用構造函數引用 Stream.of("A", "BB", "CCC", "DDDD", "FFFFF") .map(ClassMate::new) //構造函數引用,由上下文決定用哪個構造函數 .collect(Collectors.toList()); }
① 第一個咱們使用的是 lambda 表達式進行建立對象的 s -> new ClassMate(s)
。
② 第二個咱們使用的是構造函數引用建立對象的 ClassMate::new
。
③ 咱們發現構造函數引用:類名::new
,而後對於使用哪個構造函數是由上下文決定的,好比有一個參數和兩個參數和無參數的構造函數,會自動肯定用哪個。
在 Java 8 以前的接口是不能有實現的,只能定義抽象方法,然而,在 Java 8 之後,增長了一個新的功能,能夠添加實現,能夠定義默認方法,能夠定義靜態方法。
什麼是函數式接口呢?
這個名詞在 Java 中之前是不多聽到的,可是正是有了 Java 8 的橫空出世,函數式編程也變得熟悉了。
在一個接口中咱們以 @FunctionalInterface
註解聲明一個接口,而且接口中只有一個抽象方法,那麼咱們就叫作這是一個函數式接口。
/** * @ClassName FunctionalInterfaceTest * @Description * @Author 歐陽思海 * @Date 2019/5/14 10:39 * @Version 1.0 **/ @FunctionalInterface public interface FunctionalInterfaceTest { //繼承接口後,又加了新的抽象方法,這個接口就再也不是函數式接口 void test(String s); }
① 上面的接口中只有一個抽象方法,因此這是一個函數式接口。
② 若是上面接口中再加一個抽象方法,那麼就不是函數式接口了。
下面,咱們再經過繼承來繼承這個接口。
/** * @ClassName FunctionalTest * @Description * @Author 歐陽思海 * @Date 2019/5/17 17:26 * @Version 1.0 **/ public interface FunctionalTest extends FunctionalInterfaceTest{ int test2(); }
① 咱們繼承了上面的接口,而且加了一個 test2
方法。
② 這裏注意,若是一個接口集成現有的函數式接口後,又加了其餘的抽象方法,這個接口就不是函數式接口了。
默認方法很簡單,用 default
聲明便可。
/** * @ClassName FunctionalInterfaceTest * @Description * @Author 歐陽思海 * @Date 2019/5/14 10:39 * @Version 1.0 **/ @FunctionalInterface public interface FunctionalInterfaceTest { //繼承接口後,又加了新的抽象方法,這個接口就再也不是函數式接口 void test(String s); //默認方法 default String getStr(){ return null; } }
① 在接口中添加了一個默認方法。而且實現了方法。
默認方法很簡單,用 static
聲明便可。
/** * @ClassName FunctionalInterfaceTest * @Description * @Author 歐陽思海 * @Date 2019/5/14 10:39 * @Version 1.0 **/ @FunctionalInterface public interface FunctionalInterfaceTest { //繼承接口後,又加了新的抽象方法,這個接口就再也不是函數式接口 void test(String s); //靜態方法 static String getStr2(){ return null; } //錯誤用法 default static String getStr3(){ return null; } }
① 實現的靜態方法,用 static
聲明。
② 注意不能同時使用 default 和 static 聲明。
在這篇文章中,咱們講了 lambda 表達式、方法引用、函數式接口、接口中的靜態方法、接口中的默認方法的使用。