最近在学习kotlin的时候,其中有一章节专门讲
kotlin
的高阶函数和lambda
表达式,两者配合使用可以让代码极致的简洁,今天 来了解一下lambda
表达式相关的知识。
在很多高级语言中都是有lambda
表达式的,比如:Python、Javascript、C#、Objective-C......
Lambda
表达式在Java 8中被引入,被称为Java 8的最大特征。Lambda表达式有助于函数式编程,并且简化了开发工作。(关于函数式编程可以看一下阮一峰的函数式编程初探)。
lambda
表达式简介
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中),使用 Lambda 表达式可以使代码变的更加简洁紧凑。但是Java中的lambda无法单独出现,它需要一个函数式接口
来盛放,lambda表达式方法体其实就是函数接口的实现。
函数式接口functional interface
我们把只拥有一个方法的接口称为 函数式接口。(之前它们被称为 SAM类型,即 单抽象方法类型(Single Abstract Method))。
例如:android中android.view.View.OnClickListener
其实就是一个函数式接口
。
/**
* 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
表达式实际场景
例如:在android中我给一个ImageView
设置了一个点击事件,代码如下:
mIvLogo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("Hello");
}
});
那么我们用lambda
表达式的代码如下:
mIvLogo.setOnClickListener(v -> System.out.println("Hello"));
匿名类型最大的问题就在于其冗余的语法。有人戏称匿名类型导致了“高度问题”(height problem):在 OnClickListener
这个例子里的五行代码中仅有一行在做实际工作,但是我们不得不写5行代码。
lambda
语法
lambda表达式由三部分组成:
Argument List | Arrow Token | Body |
---|---|---|
(int x, int y) | -> | x + y |
lambda 表达式的语法格式如下:
(parameters) -> expression 或 (parameters) ->{ statements; }
以下是lambda表达式的重要特征:
- 可选类型声明:无需声明参数的类型。编译器可以跟参数的值推断出参数的类型。
- 可选的参数圆括号:一个参数无需定义圆括号,但多个参数必须定义圆括号。
-
可选的大括号:如果
Body
只包含一个语句,可以不使用大括号。 -
可选的返回关键字:如果
Body
只有一个表达式返回值则编译器会自动返回值(无需写return关键字),需要花括号表示表达式返回值。
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;
//带有大括号的返回语句
MathOperation multiplication = (int a, int b) -> { return a * b; };
//不带大括号和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));
//参数不带圆括号
GreetingService greetService1 = message ->
System.out.println("Hello " + message);
//参数带圆括号
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
表达式在android中使用
android studio配置
下面介绍一下官方和三方的支持:
android官方支持
在Android Studio 3.0之后
Android Studio 3.0预览1及更高版本支持对Java 8语言进行了支持,要想使用java8的功能,请确保你的Android Plugin for Gradle版本为3.0.0-alpha1(或更高)。然后在你模块级别的 build.gradle
文件中添加以下内容:
android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
在Android Studio 3.0之前
要为您的项目启用 Java 8 语言功能和 Jack,请在主model的 build.gradle
文件中输入以下内容:
android {
...
defaultConfig {
...
jackOptions {
enabled true
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
注意:
- Jack 仅在 Android Studio 2.1 和更高版本上才受支持。
- 使用Jack的话将会导致Instant Run不可用
三方支持库
下面介绍一下如何使用:
step1 在project级别的 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后执行", 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;
});
注意:必须是函数式接口才可以使用lambda表达式。
android的场景其实很多的,在以后的使用过程中,我会把比较典型的陆续补充上来。
参考文档
oracle官网文档 Lambda Quick Start
oracle官网文档 Lambda Expressions
android官方文档 使用 Java 8 语言功能
android studio 3.0预览版功能介绍 Use Java 8 language features
原文地址:https://zhouyang-cn.github.io/2017/06/10/lambda-expressions/
转载请注明原文地址,谢谢!。
网友评论