Lambda表达式 简介 语法 示例 匿名内部类

在AS中使用 Lambda 表达式

Gradle(Project级别)中添加classpath
 
    
  1. buildscript {
  2. dependencies {
  3. classpath 'com.android.tools.build:gradle:2.2.2'
  4. classpath 'me.tatarka:gradle-retrolambda:3.2.0'
  5. }
  6. }
Gradle(app级别)中添加apply(第一行)
 
    
  1. apply plugin: 'com.android.application'
  2. apply plugin: 'me.tatarka.retrolambda'
Gradle(app级别)的android下添加compileOptions(android标签下)
 
    
  1. android {
  2. ***
  3. compileOptions {
  4. targetCompatibility 1.8
  5. sourceCompatibility 1.8
  6. }
  7. }
JDK版本选择1.8
795730-20170727090002828-1228195489.png

在Eclipse中使用 Lambda 表达式

前提条件
  • 1、安装了 JDK 8 的 JRE
  • 2、所使用的 Eclipse 要支持 Java8 的编译
在 Eclipse 中,选择 Windows > Preferences > Java > Installed JREs,勾选JDK 8 的 JRE
选择 Windows > Preferences > Java >Compiler,然后将 Compiler compliance level 设为 1.8。如果没有1.8的选项,说明此eclipse版本不支持。

单击 Apply,然后单击 OK。

Eclipse Luna  SR2已经添加了对Java8的支持,可直接到官网下载

使用示例

1、没有参数
 
    
  1. new Thread(() -> {
  2. Log.i("bqt", "包青天");//必须有分号
  3. }).start();
只有一行语句时,可以进一步简化为:
 
    
  1. new Thread(() -> Log.i("bqt", "包青天")).start();
但是如果有多行 语句 ,就没法简化了

2、单一参数
 
    
  1. listView.setOnClickListener(v -> {
  2. Toast.makeText(ctx, "包青天", Toast.LENGTH_SHORT).show();//必须有分号
  3. });
同样,只有一行语句时,可以进一步简化为:
 
    
  1. istView.setOnClickListener(v -> Toast.makeText(ctx, "包青天", Toast.LENGTH_SHORT).show());

3、多个参数
 
    
  1. listView.setOnItemClickListener((parent, view, position, id) -> {
  2. Toast.makeText(ctx, "position=" + position, Toast.LENGTH_SHORT).show();//必须有分号
  3. });
同样, 只有一行语句时, 可以进一步简化为:
 
    
  1. listView.setOnItemClickListener((parent, view, position, id) -> Toast.makeText(ctx, "position=" + position, Toast.LENGTH_SHORT).show());

常见的不能使用的情况

1、如果有多个需要实现的方法,则不能使用,如:
 
    
  1. listView.setOnScrollListener(new AbsListView.OnScrollListener() {
  2. @Override
  3. public void onScrollStateChanged(AbsListView view, int scrollState) {
  4. }
  5. @Override
  6. public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
  7. }
  8. });
2、如果需要在匿名内部类中定义成员变量,则不能使用,如:
 
    
  1. listView.setOnClickListener(new View.OnClickListener() {
  2. private boolean b;
  3. @Override
  4. public void onClick(View v) {
  5. }
  6. });
3、 如果 需要在匿名内部类中使用到this、super等(注意这里的this是指匿名内部类,而非如MainActivity.this这样的外部类) ,则不能使用,如:
 
    
  1. view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
  2. @Override
  3. public void onGlobalLayout() {
  4. //这里的this代表的是匿名内部类OnGlobalLayoutListener
  5. view.getViewTreeObserver().removeOnGlobalLayoutListener(this);//使用到了this
  6. }
  7. });

演示代码

 
    
  1. public class LambdaTestActivity extends ListActivity {
  2. private ImageView iv;
  3. protected void onCreate(Bundle savedInstanceState) {
  4. super.onCreate(savedInstanceState);
  5. String[] array = {"没有参数",
  6. "没有参数,精简模式",
  7. "Runnable + runOnUiThread",
  8. "单一参数",
  9. "方法引用",
  10. "多个参数",
  11. "迭代,方法引用",};
  12. setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, new ArrayList<>(Arrays.asList(array))));
  13. iv = new ImageView(this);
  14. iv.setImageResource(R.drawable.icon);
  15. getListView().addFooterView(iv);
  16. }
  17. @RequiresApi(api = Build.VERSION_CODES.N)
  18. @Override
  19. protected void onListItemClick(ListView listView, View view, int position, long id) {
  20. switch (position) {
  21. case 0:
  22. new Thread(() -> {
  23. Log.i("bqt", "包青天");
  24. }).start();
  25. break;
  26. case 1:
  27. new Thread(() -> Log.i("bqt", "白乾涛")).start();
  28. break;
  29. case 2:
  30. new Thread(() -> {
  31. //Lambda 主体中的 this、super 引用与封闭上下文中一样,因为 lambda 表达式不会引入新的作用域,这与匿名类不同。
  32. runOnUiThread(() -> Toast.makeText(this, "包青天", Toast.LENGTH_SHORT).show());
  33. }).start();
  34. break;
  35. case 3:
  36. iv.setOnClickListener(v -> Toast.makeText(this, "包青天:" + (v == iv), Toast.LENGTH_SHORT).show());
  37. iv.performClick();
  38. break;
  39. case 4:
  40. iv.setOnClickListener(System.out::println);//方法引用。适用条件:①功能接口方法中的参数是要传到引用方法中作为参数 ②没有返回值
  41. iv.performClick();
  42. break;
  43. case 5:
  44. iv.setOnFocusChangeListener((v, hasFocus) -> Toast.makeText(this, "hasFocus:" + hasFocus, Toast.LENGTH_SHORT).show());
  45. iv.performClick();
  46. break;
  47. case 6:
  48. List<String> list = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
  49. list.forEach(s -> Log.i("bqt", s));//@RequiresApi(api = Build.VERSION_CODES.N)
  50. break;
  51. }
  52. }
  53. }

Lambda 表达式简介

Lambda 表达式也称为闭包,是匿名内部类的简短形式。Lambda 表达式简化了【单一抽象方法声明接口】的使用,因此 lambda 表达式也称为功能接口。
使用 lambda 表达式实现功能接口时,无需创建类或匿名类。
Lambda 表达式只能用于单一方法声明接口,也即 功能接口(只有一个抽象方法的接口)
Lambda 表达式具有以下优点:
  • 简明的语法
  • 方法引用和构造函数引用
  • 相比于匿名类,减少了运行时开销
  • Lambda 表达式的语法

Lambda 表达式语法

基本语法
 
    
  1. (formal parameter list) -> { expression or statements }
参数列表是一个逗号分隔的形式参数列表,这些参数与功能接口中单一方法的形式参数相对应。
参数列表中的参数类型是可选项,如果未指定参数类型,将从上下文推断。
参数列表必须用小括号括起来,但如果只有一个参数且不带参数类型时 小括号 可以省略。
参数列表如果为空(即:功能接口方法没有形式参数),则必须指定空括号。
参数列表后面是 -> 运算符,然后是 lambda 主体,即单一表达式或语句块。

Lambda 主体根据以下选项之一返回结果:
  • 如果 lambda 主体是单一表达式,则返回表达式的值(如果有的话)。
  • 如果功能接口方法的结果是 void,可以提供一个 return 语句,但这不是必需的。
  • 如果功能接口方法具有返回类型,且 lambda 主体不是单一表达式,则 lambda 主体必须使用 return 语句返回匹配的值。
语句块必须包含在大括号内,除非语句块是一个方法调用语句,且 功能接口 方法 的返回结果是void。

Lambda 表达式实际上是一种匿名方法实现,指定形式参数,并使用 return 语句返回值。
匿名方法必须按照以下规则所规定的与其实现的功能接口方法兼容。
  • Lambda 表达式返回的结果必须与功能接口方法的结果兼容。返回值的类型可以是功能接口方法声明中返回类型的子类型。
  • Lambda 表达式签名必须与功能接口方法的签名相同。
  • Lambda 表达式只能抛出那些在功能接口方法的 throws 子句中声明了异常类型或异常超类型的异常。

Lambda 表达式中的局部变量

Lambda 表达式不会定义新的作用域,lambda 表达式的作用域与封闭作用域相同。
如果 Lambda 主体声明的局部变量与封闭作用域内的变量重名,将产生编译器错误
 
    
  1. Lambda expression's local variable i cannot re-declare another local variable defined in an enclosing scope
局部变量无论是在 lambda 表达式主体中声明,还是在封闭作用域中声明,使用之前都必须先初始化,否则将产生编译器错误
 
    
  1. The local variable i may not have been initialized
lambda 表达式中使用的变量必须处于终态或等效终态,否则将产生编译器错误
 
    
  1. Variable i is required to be final or effectively final
Lambda 主体中的 this 和 super 引用与封闭上下文中一样,因为 lambda 表达式不会引入新的作用域,这与匿名类不同。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值