首页  >  文章  >  Java  >  详细介绍Android使用Java8新特性之Lambda expression的示例代码

详细介绍Android使用Java8新特性之Lambda expression的示例代码

黄舟
黄舟原创
2017-03-11 11:54:451954浏览

前言

Lambda expression,java8的新特性。使用Lambda expression,可以替代只有一个函数的接口实现,告别匿名内部类,代码看起来更简洁易懂。
java8还有其它一些新特性,不过在android上可能都无法使用。
studio 2.x后 支持jack编译器,使用它,能使用java8的Lambda expression,但其它特性也不敢保证就能用。

注:Android SDK中集成了JDK的一些源码,有些原生JDK中的类,可能增加了新特性的一些实现,但Android中的并没有。再比如java8的java.util.function包,在低版本中也是没有的

还可以使用插件retrolambda来支持java8的Lambda expression。

Jack 配置

添加如下配置

android {
    jackOptions {
        enabled true
    }
    compileOptions {//jack、retrolambda编译必需        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

以启用jack编译器,来支持Lambda expression

使用最新2.3版studio,jdk 1.8 的环境, gradle2.3,和如上的配置
 经测试,在4.4的模拟器上也是可以跑的
 配置Demo : http://www.php.cn/

retrolambda 配置

retrolambda 兼容java5、6、7使用Lambda expression。

配置如下

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.3'
        classpath 'me.tatarka:gradle-retrolambda:3.6.0'
    }}
apply plugin: 'me.tatarka.retrolambda'android {
    defaultConfig {
        minSdkVersion 11 //这个没有硬性要求
    }
    compileOptions {//jack、retrolambda编译必需
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }}

注:很多开源的项目,还是使用的retrolambda

Lambda expression的使用方式

首先,我们要知道的是,该表达式,整体上是表达了一个『对象类型』。

最简单的Lambda expression

代码:

Runnable runnable = () -> System.out.println("hi, 我是 stone");runnable.run();

()其实就是方法参数列表,这里没有传参数,那么就会去匹配无参的方法,因Runnable只有一个void run(),所以会匹配到它;这里没有写方法名,所以方法的名字会被忽略。

-> 这个后面跟方法体。这里只有一句打印代码,可以省略方法体的花括号:{} 。

注:这里还省略了”new Runnable”这样的代码,是因为编译器会进行自动的类型推断。如果直接调用 () -> System.out.println(“hi, 我是 stone”).run(); 那么是编译不过的,因为编译器不知道去哪个类里找对应的方法

有参数且有返回值的Lambda expression

代码:

button.setOnTouchListener((view, event)-> {    
if (event.getAction() == MotionEvent.ACTION_DOWN) {        
if (flag) {            
return true;
        }
    }    return super.onTouchEvent(event);
});

有参数时,只要传参数名字即可,名字可随意定义;类型定义或不定义都可以;不定义时,编译器会自动推断。
有返回值时,可以在方法体中,使用return;也可以在只有一段代码时,省略return,如下:

button.setOnTouchListener((v, e) -> super.onTouchEvent(e));

自定义接口,并使用Lambda expression

首先定义只有一个抽象方法的接口:

    interface IGetData<T> {//lambda只能用于单一方法类型匹配
        T get();//      T getOne(int i); //多个抽象方法,直接编译不过
    }

定义方法,参数为上面定义的接口:

    void print(IGetData<String> data) {        
    String msg = data.get();        
    System.out.println(msg);
    }

使用Lambda expression 作为参数, 调用print():

        print(() -> "张三");        print(() -> {
            System.out.println("干活了");            return "李四";
        });

输出:

03-08 06:46:00.430 1510-1510/? I/System.out: 张三
03-08 06:46:00.430 1510-1510/? I/System.out: 干活了
03-08 06:46:00.430 1510-1510/? I/System.out: 李四

使用Lambda expression简化命令者模式

命令者模式的特征及简单实现流程:

  • 一个命令者 接口, 定义 一个统一执行命令的抽象方法

  • 每个具体命令者都实现 命令者接口,并依赖一个 接收者对象,  命令的执行代理给接收者来执行

  • 调用者类,依赖一个命令者接口对象,由命令者接口来执行。 多态传入不同的具体命令者, 最终由接收者采取不同的执行方式

示例 (原来的实现)

比如,有一些文件操作命令:open, close, save, delete,接收者为一个编辑器editor
那,首先,需要定义一个命令接口:IAction

public interface IAction {//原 命令者  抽象出一个 执行命令的方法
    void perform();
}

再定义四个具体命令者类OpenAction、CloseAction、SaveAction、DeleteAction。
CloseAction代码:

public class CloseAction implements IAction {
    private Editor mEditor;    
    public CloseAction(Editor editor) {        
    this.mEditor = editor;
    }    
    @Override
    public void perform() {        
    this.mEditor.close();
    }
}

其他三个实现与CloseAction类似。

Editor类(接收者),就定义了收到四个命令的各个具体实现:

public class Editor {     public void save() {
          System.out.println("save");
      }      public void delete() {
          System.out.println("delete");
      }      public void open() {
          System.out.println("open");
      }      public void close() {
          System.out.println("close");
      }
}

注:如果说不同的编辑器对这些命令都有各自不同的实现,那么也可以定义一个IEditor接口,再实现不同的Editor。关于此点就不详细讨论了

最后还要有一个调用者,可以是一个类:

public class Invoker {  
    private IAction action;  

    public Invoker(IAction action) {  
        this.action = action;  
    }  

    public void invoke() {  
        this.action.perform();  
    }  
}

client发起命令:

Editor editor = new Editor();
new Invoker(new OpenAction(editor)).invoke();
new Invoker(new CloseAction(editor)).invoke();
new Invoker(new SaveAction(editor)).invoke();
new Invoker(new DeleteAction(editor)).invoke();

这里的调用者,可以不使用类的方式定义,而是定义成client中的一个方法:

private void invoke(IAction action) {
    action.perform();
}

client发起命令调用:

 invoke(new OpenAction(editor)); 
 invoke(new CloseAction(editor)); 
 invoke(new SaveAction(editor)); 
 invoke(new DeleteAction(editor));

Lambda expression 简化版

保留IAction、Editor和 client中的invoke(Iaction action)。

client发起命令调用:

  Editor editor = new Editor();
  invoke(() -> editor.open());  
  invoke(() -> editor.close());  
  invoke(() -> editor.save());  
  invoke(() -> editor.delete());

这样,使用Lambda expression后,就省略了具体命令者类的定义。并能一目了然地看到最终执行的是哪个方法。

不用担心这样书写后,会破坏原本命令者模式的 请求与执行分离 的作用。
因 invoke(() -> editor.open());   209861d5cd2975725c730f519ed6ad71

invoke(new IAction() {    @Override
    public void perform() {
        editor.open();
    }
});

如果保留调用类Invoker,那就类似如下调用:

new Invoker(() -> editor.open()).invoke();

以上是详细介绍Android使用Java8新特性之Lambda expression的示例代码的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn