首頁  >  文章  >  Java  >  詳細介紹Android使用Java8新功能之Lambda expression的範例程式碼

詳細介紹Android使用Java8新功能之Lambda expression的範例程式碼

黄舟
黄舟原創
2017-03-11 11:54:451943瀏覽

前言

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