最近在學(xué)習(xí)kotlin的時(shí)候舟陆,其中有一章節(jié)專門講
kotlin
的高階函數(shù)和lambda
表達(dá)式浪感,兩者配合使用可以讓代碼極致的簡潔,今天 來了解一下lambda
表達(dá)式相關(guān)的知識(shí)。
在很多高級(jí)語言中都是有lambda
表達(dá)式的擎值,比如:Python、Javascript逐抑、C#鸠儿、Objective-C......
Lambda
表達(dá)式在Java 8中被引入,被稱為Java 8的最大特征厕氨。Lambda表達(dá)式有助于函數(shù)式編程进每,并且簡化了開發(fā)工作。(關(guān)于函數(shù)式編程可以看一下阮一峰的函數(shù)式編程初探)命斧。
lambda
表達(dá)式簡介
Lambda 允許把函數(shù)作為一個(gè)方法的參數(shù)(函數(shù)作為參數(shù)傳遞進(jìn)方法中)田晚,使用 Lambda 表達(dá)式可以使代碼變的更加簡潔緊湊。但是Java中的lambda無法單獨(dú)出現(xiàn)国葬,它需要一個(gè)函數(shù)式接口
來盛放贤徒,lambda表達(dá)式方法體其實(shí)就是函數(shù)接口的實(shí)現(xiàn)芹壕。
函數(shù)式接口functional interface
我們把只擁有一個(gè)方法的接口稱為 函數(shù)式接口。(之前它們被稱為 SAM類型接奈,即 單抽象方法類型(Single Abstract Method))踢涌。
例如:android中android.view.View.OnClickListener
其實(shí)就是一個(gè)函數(shù)式接口
。
/**
* Interface definition for a callback to be invoked when a view is clicked.
*/
public interface OnClickListener {
/**
* Called when a view has been clicked.
*
* @param v The view that was clicked.
*/
void onClick(View v);
}
lambda
表達(dá)式實(shí)際場景
例如:在android中我給一個(gè)ImageView
設(shè)置了一個(gè)點(diǎn)擊事件序宦,代碼如下:
mIvLogo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("Hello");
}
});
那么我們用lambda
表達(dá)式的代碼如下:
mIvLogo.setOnClickListener(v -> System.out.println("Hello"));
匿名類型最大的問題就在于其冗余的語法睁壁。有人戲稱匿名類型導(dǎo)致了“高度問題”(height problem):在 OnClickListener
這個(gè)例子里的五行代碼中僅有一行在做實(shí)際工作,但是我們不得不寫5行代碼互捌。
lambda
語法
lambda表達(dá)式由三部分組成:
Argument List | Arrow Token | Body |
---|---|---|
(int x, int y) | -> | x + y |
lambda 表達(dá)式的語法格式如下:
(parameters) -> expression 或 (parameters) ->{ statements; }
以下是lambda表達(dá)式的重要特征:
- 可選類型聲明:無需聲明參數(shù)的類型堡僻。編譯器可以跟參數(shù)的值推斷出參數(shù)的類型。
- 可選的參數(shù)圓括號(hào):一個(gè)參數(shù)無需定義圓括號(hào)疫剃,但多個(gè)參數(shù)必須定義圓括號(hào)钉疫。
-
可選的大括號(hào):如果
Body
只包含一個(gè)語句,可以不使用大括號(hào)巢价。 -
可選的返回關(guān)鍵字:如果
Body
只有一個(gè)表達(dá)式返回值則編譯器會(huì)自動(dòng)返回值(無需寫return關(guān)鍵字)牲阁,需要花括號(hào)表示表達(dá)式返回值。
lambda
語法范例
public class Java8Tester {
public static void main(String[] args) {
Java8Tester tester = new Java8Tester();
//含類型聲明
MathOperation addition = (int a, int b) -> a + b;
//無類型聲明
MathOperation subtraction = (a, b) -> a - b;
//帶有大括號(hào)的返回語句
MathOperation multiplication = (int a, int b) -> { return a * b; };
//不帶大括號(hào)和return語句
MathOperation division = (int a, int b) -> a / b;
System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
System.out.println("10 / 5 = " + tester.operate(10, 5, division));
//參數(shù)不帶圓括號(hào)
GreetingService greetService1 = message ->
System.out.println("Hello " + message);
//參數(shù)帶圓括號(hào)
GreetingService greetService2 = (message) ->
System.out.println("Hello " + message);
greetService1.sayMessage("Mahesh");
greetService2.sayMessage("Suresh");
}
interface MathOperation {
int operation(int a, int b);
}
interface GreetingService {
void sayMessage(String message);
}
private int operate(int a, int b, MathOperation mathOperation){
return mathOperation.operation(a, b);
}
}
lambda
表達(dá)式在android中使用
android studio配置
下面介紹一下官方和三方的支持:
android官方支持
在Android Studio 3.0之后
Android Studio 3.0預(yù)覽1及更高版本支持對(duì)Java 8語言進(jìn)行了支持壤躲,要想使用java8的功能城菊,請(qǐng)確保你的Android Plugin for Gradle版本為3.0.0-alpha1(或更高)。然后在你模塊級(jí)別的 build.gradle
文件中添加以下內(nèi)容:
android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
在Android Studio 3.0之前
要為您的項(xiàng)目啟用 Java 8 語言功能和 Jack碉克,請(qǐng)?jiān)谥鱩odel的 build.gradle
文件中輸入以下內(nèi)容:
android {
...
defaultConfig {
...
jackOptions {
enabled true
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
注意:
- Jack 僅在 Android Studio 2.1 和更高版本上才受支持凌唬。
- 使用Jack的話將會(huì)導(dǎo)致Instant Run不可用
三方支持庫
下面介紹一下如何使用:
step1 在project級(jí)別的 build.gradle
文件中添加如下代碼:
buildscript {
repositories {
// Required because retrolambda is on maven central
mavenCentral()
}
dependencies {
classpath 'me.tatarka:gradle-retrolambda:3.6.1'
}
}
step2 在主model的 build.gradle
文件中添加如下代碼:
apply plugin: 'me.tatarka.retrolambda'
android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
在android中的使用場景
new Handler().postDelayed(() -> {
Toast.makeText(this, "2s后執(zhí)行", Toast.LENGTH_SHORT).show();
}, 2000);
mIvLogo.setOnLongClickListener(v -> {
System.out.println("onLongClick");
return false;
});
mIvLogo.setOnTouchListener((v, event) -> {
if(event.getAction() == MotionEvent.ACTION_DOWN){
System.out.println("ACTION_DOWN");
}
return false;
});
注意:必須是函數(shù)式接口才可以使用lambda表達(dá)式。
android的場景其實(shí)很多的漏麦,在以后的使用過程中客税,我會(huì)把比較典型的陸續(xù)補(bǔ)充上來。
參考文檔
oracle官網(wǎng)文檔 Lambda Quick Start
oracle官網(wǎng)文檔 Lambda Expressions
android官方文檔 使用 Java 8 語言功能
android studio 3.0預(yù)覽版功能介紹 Use Java 8 language features
原文地址:https://zhouyang-cn.github.io/2017/06/10/lambda-expressions/
轉(zhuǎn)載請(qǐng)注明原文地址撕贞,謝謝更耻!。