1. 程式人生 > >第三章(3) lambda表示式型別檢查、型別推斷以及區域性變數

第三章(3) lambda表示式型別檢查、型別推斷以及區域性變數

     1.型別檢查

     當我們在之前第一次提到lambda表示式的時候,說它可以為函式式介面生成一個例項。然而,Lambda表示式本身並不包含它在實現哪個函式式介面的資訊。為了全面瞭解Lambda表示式,你應該知道Lambda的實際型別是什麼。

      Lambda的型別是從使用Lambda的上下文推斷出來的。

       所謂上下文,舉個例子,比如說lambda表示式的引數與函式式介面內方法的引數,返回值型別相互對應。

       lambda表示式需要的型別,或者說lambda實現的那個函式式介面稱之為目標型別。

       比如下面這段程式碼,當你使用lambda的時候,它背後發生了什麼。看看lambda表示式的型別檢查過程。

 

 首先,你要找出filter方法的宣告。

•第二,要求它是Predicate<Apple>(目標型別)物件的第二個正式引數。

•第三,Predicate<Apple>是一個函式式介面,定義了一個叫作test的抽象方法。

•第四,test方法描述了一個函式描述符,它可以接受一個Apple,並返回一個boolean。

•最後,filter的任何實際引數都必須匹配這個要求。

2.型別推斷

       你已經見過如何利用目標型別來檢查一個Lambda是否可以用於某個特定的上下文。其實,它也可以用來做一些略有不同的事:推斷Lambda引數的型別。比如下面這段程式碼例子:

我們 知道這其中的lambda是完全沒有問題的,但是我們的編譯器卻可以像下面這樣神奇的推斷出lambda表示式的引數型別,而不必我們顯示的去宣告:

怎麼樣,是不是很流弊?我們的編譯器會根據上下文自動的推斷出引數a的型別就是Pig

請注意,有時候顯式寫出型別更易讀,有時候去掉它們更易讀。沒有什麼法則說哪種更好;對於如何讓程式碼更易讀,程式設計師必須做出自己的選擇。

3.使用區域性變數

    我們看到,我們現在為止lambda都只用到了主體裡的引數,但是lambda表示式也允許使用自由變數。不是引數,而是在外層作用域中定義的變數:

對於引用外部變數,你可以沒有限制的引用例項變數和靜態變數,但是區域性變數必須宣告為final,或者它實際上是final

對於上面的例子,雖然他沒有被顯示的宣告為finl,但是num變數只被賦值了一次,也就符合了“實際上是final”的條件,但是下面這種情況是無法編譯通過的,我們再次對num賦值: