• 技术文章 >Java >java教程

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

    黄舟黄舟2017-03-11 11:54:45原创912

    前言

    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 : //m.sbmmt.com/

    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()); <==>

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

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

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

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

    声明:本文原创发布php中文网,转载请注明出处,感谢您的尊重!如有疑问,请联系admin@php.cn处理
    上一篇:Android适配器(Adapter)、观察者(Observer) 模式的代码分析(图) 下一篇:详细介绍Java FTP上传下载删除功能实例代码
    大前端线上培训班

    相关文章推荐

    • 理解java8中java.util.function.*pojo反射新方法(附代码)• 浅析安卓app和微信授权登录及分享完整对接(代码分享)• 教你一招搞定时序数据库在Spring Boot中的使用• 一招教你使用java快速创建Map(代码分享)• PlayFramework 完整实现一个APP(十一)

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网