逛帖子的時候偶爾發(fā)現(xiàn)了一篇lambda很容易入門的帖子,轉載于30分鐘入門Java8之lambda表達式
前言
Google在今年發(fā)布Android N開發(fā)者預覽版耐齐,一并宣布開始支持Java 8
。我們終于能在Android
開發(fā)中使用到Java8
的一些語言特性了。目前支持:
- 默認方法
- lambda表達式
- 多次注解
今天我們就簡要學習lambda表達式。
配置開發(fā)環(huán)境
首先需要下載安裝JDK1.8
。
如果想在Android
開發(fā)中使用lambda
表達式萧落,需要在Android Studio
中配置Java 8
開發(fā)環(huán)境怎虫。
配置app
的Gradle
文件,不是Project
的Gradle
:
- 開啟jack編譯選項
- 設置編譯選項兼容到1.8
android {
defaultConfig {
...
//開啟jack編譯
jackOptions {
enabled true
}
}
...
//將編譯選項設置為Java1.8
compileOptions {
targetCompatibility 1.8
sourceCompatibility 1.8
}
}
出于種種原因茴丰,可能我們使用的JDK版本是1.7甚至更低,但是我們又想學習使用lambda表達式姐刁,怎么辦呢芥牌?Github上已經有開發(fā)者設計了兼容lambda表達式到Java7,6聂使,5的開源庫retrolamda壁拉。至于如何在Android Studio中配置,在此就不啰嗦了柏靶∑恚可以參看Gradle Retrolambda Plugin。
第一個lambda表達式
看到下面的代碼屎蜓,相信大家都會非常熟悉痘昌。這不就是給button
設置監(jiān)聽事件嘛。
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("TAG","按鈕被點擊,匿名內部類");
}
});
分析上面的代碼炬转,這是通過匿名內部類來設置Button
的點擊監(jiān)聽事件的辆苔。也就是說,我們創(chuàng)建了一個實現(xiàn)了View.OnClickListener
接口的匿名類的對象扼劈。匿名內部類實現(xiàn)了onClick
方法驻啤。通過這個匿名類的對象,我們在用戶點擊按鈕時荐吵,打印出日志骑冗。
可是,大家有沒有發(fā)現(xiàn)捍靠。上面那段代碼沐旨,真正有用的就是Log.d("TAG","按鈕被點擊,匿名內部類");
這一行代碼森逮,這就反映了使用匿名內部類的缺點:
- 可讀性差榨婆,不能直接明了的體現(xiàn)我們的意圖。
- 啰嗦褒侧,一行邏輯代碼卻有幾行模板代碼良风。
而lambda表達式很好的解決了這些問題:
button.setOnClickListener(view-> Log.d(TAG,"按鈕被點擊,lambda表達式"));
view-> Log.d(TAG,"按鈕被點擊,lambda表達式"));
就是我們寫的第一個lambda表達式谊迄。
lambda表達式通常以(argument)->(body)
這樣的格式書寫。
//省略參數類型
(arg1,arg2...) -> {body}
//指定參數類型
(Type1 arg1,Type2 arg2...)->{body}
lambda表達式中烟央,參數的類型可省略统诺。Java編譯器根據表達式的上下文推導出參數的類型。就像上面圖中view
的類型是View
疑俭。
lambda表達式的結構
- 參數可以是零個或多個
- 參數類型可指定粮呢,可省略(根據表達式上下文推斷)
- 參數包含在圓括號中,用逗號分隔
- 表達式主體可以是零條或多條語句,包含在花括號中
- 表達式主體只有一條語句時,花括號可省略
- 表達式主體有一條以上語句時钞艇,表達式的返回類型與代碼塊的返回類型一致
- 表達式只有一條語句時啄寡,表達式的返回類型與該語句的返回類型一致
//零個
()-> System.out.println("no argument");
//一個
x->x+1
//兩個
(x,y)->x+y
//省略參數類型
View.OnClickListener oneArgument = view->Log.d(TAG,"one argument");
//指定參數類型
View.OnClickListener oneArgument = (View view)->Log.d(TAG,"one argument");
//多行語句
//返回類型是代碼塊返回的void
View.OnClickListener multiLine = (View view)->{
Log.d(TAG,"multi statements");
Log.d(TAG,"second line");
}
//返回類型是表達式主體語句的返回類型int
(int x)->x+1
lambda表達式的類型
我們都知道,Java是一種強類型語言哩照。所有的方法參數都有類型挺物,那么lambda
表達式是一種什么類型呢?
View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View v) {
//...
}
};
button.setOnClickListener(listener);
如上所示飘弧,以往我們是通過使用單一方法的接口來代表一個方法并且重用它识藤。
在lambda表達式中,仍使用的和之前一樣的形式次伶。我們叫做函數式接口(functional interface)
如我們之前button的點擊響應事件使用的View.OnClickListener
就是一個函數式接口痴昧。
public class View implements Drawable.Callback, KeyEvent.Callback,
AccessibilityEventSource {
...
public interface OnClickListener {
void onClick(View v);
}
...
}
那究竟什么樣的接口是函數式接口呢?
函數式接口是只有一個抽象方法的接口冠王。用作表示lambda表達式的類型剪个。
Java8 API中新增了許多函數式接口:
接口名 | 參數 | 返回值 | 用途 |
---|---|---|---|
Predicate | T | boolean | 斷言 |
Consumer | T | void | 消費 |
Function | T | R | 函數 |
Function | T | R | 函數 |
Supplier | None | T | 工程方法 |
UnaryOperator | T | T | 邏輯非 |
BinaryOperator | (T,T) | T | 二元操作 |
想學習java8更多技術的童鞋可以看看下面這些文章:
深入理解Java 8 Lambda(語言篇——lambda,方法引用版确,目標類型和默認方法)