android studio 下配置java8環境
首先,你的java版本得是java8,在build.gradle下配置java8
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
如果你的項目中結合了Rxjava,需要配置
jackOptions {
enabled true
}
jack工具鏈是android在6.0版本添加的編譯器,也就是說android6.0版本的代碼都是jack工具鏈編譯的,但是安卓官方開發者網站已經放出blog,在以后的android studio中,開始支持java8,開始廢棄jack(具體什么時間,引用官網的原話:Moving forward, Java 8 language features will be natively supported by the Android build system。),但是之前使用的jack風格的代碼依然支持,附上官網鏈接
Lambda表達式
要理解lambda表達式,首先要了解的是函數式接口(functional interface)。簡單來說,函數式接口是只包含一個抽象方法的接口。比如Java標準庫中的java.lang.Runnable和java.util.Comparator都是典型的函數式接口。對于函數式接口,除了可以使用Java中標準的方法來創建實現對象之外,還可以使用lambda表達式來創建實現對象。這可以在很大程度上簡化代碼的實現。在使用lambda表達式時,只需要提供形式參數和方法體。由于函數式接口只有一個抽象方法,所以通過lambda表達式聲明的方法體就肯定是這個唯一的抽象方法的實現,而且形式參數的類型可以根據方法的類型聲明進行自動推斷。
在工作中創建一個線程的寫法如下:
/**
demo1
**/
public void runThread() {
new Thread(new Runnable() {
public void run() {
System.out.println("test");
}
}).start();
}
java8中lambda表達式一般格式
(argument) -> {body}
argument表示的是方法中的形式參數,如果沒有直接放空,后面的body是方法體
所以demo1中的代碼可以簡化如下
/**
demo2
**/
public void runThread() {
new Thread(
() -> {System.out.println("test");}
).start();
}
方法體總只有一句代碼所以可以繼續簡化
/**
demo3
**/
public void runThread() {
new Thread(
() -> System.out.println("test");
).start();
}
下面是一些常見的lambda表達式,可以加上參數類型
(int a, int b) -> { return a + b; }
() -> System.out.println("Hello World");
(String s) -> { System.out.println(s); }
() -> 42
() -> { return 3.1415 };
a -> return a * a; // 形式參數中只有a
你也可以自己編寫函數式接口
@FunctionalInterface
public interface Annimal {
public abstract void play();
}
@FunctionalInterface是 Java 8 新加入的一種接口,用于指明該接口類型聲明是根據 Java 語言規范定義的函數式接口。Java 8 還聲明了一些 Lambda 表達式可以使用的函數式接口,當你注釋的接口不是有效的函數式接口時,可以使用 @FunctionalInterface 解決編譯層面的錯誤。
另外,在java8中接口支持方法的實現,對函數式接口并不影響
@FunctionalInterface
@RequiresApi(api = Build.VERSION_CODES.N)
public interface Annimal {
public abstract void play();
default void fly(){
System.out.println("fly");
}
static void eat(){
System.out.println("eat");
}
}
上面的書寫并不會編譯報錯,也是符合規范的,但是如果添加普通的方法就會報錯,所以最好在接口上使用注解@FunctionalInterface進行聲明,以免團隊的其他人員錯誤地往接口中添加新的方法。
Lambda 表達式與匿名類的區別
使用匿名類與 Lambda 表達式的一大區別在于關鍵詞的使用。對于匿名類,關鍵詞 this
解讀為匿名類,而對于 Lambda 表達式,關鍵詞 this
解讀為寫就 Lambda 的外部類。
Lambda 表達式與匿名類的另一不同在于兩者的編譯方法。Java 編譯器編譯 Lambda 表達式并將他們轉化為類里面的私有函數,它使用 Java 7 中新加的 invokedynamic
指令動態綁定該方法,關于 Java 如何將 Lambda 表達式編譯為字節碼,Tal Weiss 寫了一篇很好的文章。