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。
新增以下設定
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 相容於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
首先,我們要知道的是,該表達式,整體上是表達了一個『物件類型』。
程式碼:
Runnable runnable = () -> System.out.println("hi, 我是 stone");runnable.run();
()其實就是方法參數列表,這裡沒有傳參數,那麼就會去匹配無參的方法,因Runnable只有一個void run(),所以會配對到它;這裡沒有寫方法名,所以方法的名字會被忽略。
-> 這個後面跟著方法體。這裡只有一句列印程式碼,可以省略方法體的花括號:{} 。
註:這裡也省略了」new Runnable」這樣的程式碼,是因為編譯器會進行自動的型別推斷。如果直接呼叫() -> System.out.println(“hi, 我是stone”).run(); 那麼是編譯不過的,因為編譯器不知道要去哪個類別找對應的方法
程式碼:
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));
#首先定義只有一個抽象方法的介面:
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: 李四
命令者模式的特徵及簡單實現流程:
一個命令者接口, 定義一個統一執行命令的抽象方法
每個特定命令者都實現命令者接口,並依賴一個接收者對象, 命令的執行代理給接收者來執行
呼叫者類,依賴一個命令者介面對象,由命令者介面來執行。 多態傳入不同的具體指令者, 最終由接收者採取不同的執行方式
例如,有一些檔案操作指令: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));
保留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中文網其他相關文章!