天天看點

函數式程式設計與lamada表達式函數式接口lamada表達式

函數式程式設計與lamada表達式

  • 函數式接口
  • lamada表達式

函數式接口

在談lamada表達式之前,有必要先了解下什麼是函數式接口。為了支援函數式程式設計,JDK8 新增了一個函數式接口FunctionalInterface。官網上有對該接口詳細介紹。如下

函數式程式設計與lamada表達式函數式接口lamada表達式

圖1 FunctionalInterface介紹圖

主要說的是,函數式接口隻能有一個抽象方法,注意,聲明為default不算在其中,或者Object裡的public方法,即使被繼承并改為abstract,也不算在其中,因為它們都是在自身或某個地方有實作的。

@FunctionalInterface
public interface testi<T> {	
	@SuppressWarnings("hiding")
	<T> void abstractMethod(T t);
		
	int hashCode();
}
           

在上面的方法中,雖然有兩個抽象方法,但是,由于hashCode屬于Object的public方法,是以,隻算abstractMethod一個,是以testi接口會被當做一個函數式接口。

函數式程式設計與lamada表達式函數式接口lamada表達式

圖2 符合定義的函數式接口不會彈錯誤提示

如果我們将hashCode改成hashCode1,由于加了FunctionalInterface注解,是以會在編譯時就發現這個錯誤,并彈出提示。testi接口不是一個函數式接口

函數式程式設計與lamada表達式函數式接口lamada表達式

圖3 不符合定義的函數式接口彈錯誤提示

對于符合函數式接口定義的接口,加不加FunctionalInterface注解都可以,但是加了之後,會在編譯時就提前檢查,能提前發現錯誤,是以官網時推薦添加該注解的。

那麼為什麼要提供這個函數式接口呢?理由是函數接口的執行個體可以用lambda表達式、方法引用或構造函數引用建立

lamada表達式

在介紹lamada表達式之前,需要先介紹下匿名内部類,因為lamada表達式通常被用作簡化建立匿名内部類。

public class CollectionTest {
	@FunctionalInterface
	public interface testi<T> {
		@SuppressWarnings("hiding")
		<T> void abstractMethod(T t);
		int hashCode();
	}

    public static void main(String[] args) throws IOException {
       Integer[] integers=new Integer[] {1,3,4,5,5,67,8,8,6};
       //傳統方式,匿名内部類
       for(Integer i:integers) {
    	   new testi<Object>() {
    		   @Override
    		   public void abstractMethod(Object t) {
    			   System.out.println(t);
    		   }
    	   }.abstractMethod(i);
       } 
    } 
}
           

如上所示

new testi<Object>() {
	@Override
   	public void abstractMethod(Object t) {
    	System.out.println(t);
    }
}.abstractMethod(i);
           

該匿名内部類的意思是,建立一個執行個體,并重寫父類抽象方法,并在建立完成後調用該方法,結果如下。

函數式程式設計與lamada表達式函數式接口lamada表達式

圖4 傳統匿名内部類輸出

将其改為lamada表達式後,代碼如下

public class CollectionTest {
	@FunctionalInterface
	public interface testi<T> {
		@SuppressWarnings("hiding")
		<T> void abstractMethod(T t);
		int hashCode();
	}

    public static void main(String[] args) throws IOException {
       fun((x) -> System.out.println("Hello World " + x)); 
    } 
    @SuppressWarnings({ "unchecked", "rawtypes" })
	static void fun(testi t) {
    	Integer[] integers=new Integer[] {1,3,4,5,5,67,8,8,6};
    	for(Integer i:integers)
    		t.abstractMethod(i);
    } 
}
           

在上述代碼中

的本質是建立一個匿名内部類,其中右邊部分為重寫方法

而左邊是傳入的參數,也就是在方法體中能被使用到,結果如下。

函數式程式設計與lamada表達式函數式接口lamada表達式

圖5 lamada表達式輸出

關于更多的lamada表達式,請參考 JDK8的新特性——Lambda表達式

但是注意,這篇部落格有個解釋得不怎麼好的地方

函數式程式設計與lamada表達式函數式接口lamada表達式

圖6 該部落格解釋不準确的點

詳情請參考上述的官方解釋

關于lamada表達式的更多用法,請參考 Lambda表達式更多用法