欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

AndroidStudio3 支持 Java8 了請問你敢用嗎

 更新時間:2017年11月09日 10:43:57   投稿:mrr  
Google 發(fā)布了 AS 3.0,以及一系列的 Support 包,有意思的新東西挺多,AS3里面有一個亮眼的特性就是支持J8。接下來通過本文給大家分享AndroidStudio3 支持 Java8 的相關內(nèi)容,感興趣的朋友一起看看吧

摘要: 今天早上,Google 發(fā)布了 AS 3.0,以及一系列的 Support 包,有意思的新東西挺多,因為之前一直在看 kotlin的支持,特地翻了一下對 Java8 的支持方式,結(jié)果……

本文開源實驗室原創(chuàng),轉(zhuǎn)載請以鏈接注明:https://kymjs.com/code/2017/10/26/01/

支持 Java 8

kotlin 相關的東西很早以前我就在講了,這里就不再細說了。AS3里面有一個亮眼的特性就是支持J8。首先說一下為什么以前我們不能用Java8的新特性,最主要的原因就是 lambda 語法。在 JVM 中,Java8 的語法是通過一個叫做invokedynamic的字節(jié)碼操作命令完成的,但是這東西在 dalvik 中并沒有,因此一直不能用。

現(xiàn)在AS3.0之所以能用,實際上是在新的Android Studio中加入了一個desugar的東西,他就類似JVM上的invokedynamic,把Java8的字節(jié)碼翻譯成dalvik可識別的。

官網(wǎng)介紹:

Android Studio provides built-in support for using certain Java 8 language features and third-party libraries that use them. As shown in figure 1, the default toolchain implements the new language features by performing bytecode transformations, called desugar, on the output of the javac compiler.

desugar 能干啥

首先看張官方圖:

desugar

在 javac 執(zhí)行后,desugar 會對 class 做操作,將內(nèi)部的lambda相關的語法轉(zhuǎn)換為dalvik可識別的語法。
說的太抽象具體表現(xiàn)我們看代碼。

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  new Thread(() -> {
    Log.d("kymjs", "========");
  }).start();
}

一個這樣的Java8 lambda語法的代碼被編譯以后,反編譯它,可以看到變成了這樣:

protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  this.setContentView(2131296283);
  (new Thread(MainActivity$$Lambda$0.$instance)).start();
}
// $FF: synthetic class
final class MainActivity$$Lambda$0 implements Runnable {
  static final Runnable $instance = new MainActivity$$Lambda$0();
  private MainActivity$$Lambda$0() {
  }
  public void run() {
    MainActivity.lambda$onCreate$0$MainActivity();
  }
}

我們看到上面的代碼,在編譯后的run()方法內(nèi)有一句MainActivity.lambda$onCreate$0$MainActivity();其實這一句就是原本lambda body,他被轉(zhuǎn)換成了 MainActivity 類中的一個 static method。在最終編譯成 dex 后會再次優(yōu)化,減少一次方法調(diào)用直接變成run方法的body(相當于內(nèi)聯(lián))。具體原理操作請見源碼的visitInvokeDynamicInsn方法:GoogleCode請自備梯子

上面的代碼演示了純函數(shù)(什么是純函數(shù)自己wiki)的操作,下面看一個非純函數(shù)的。
編譯前:

public class MainActivity extends AppCompatActivity {
  String mString = "hello";
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    new Thread(() -> {
      Log.d("kymjs", "========" + mString);
    }).start();
  }
}

編譯后:

protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  this.setContentView(2131296283);
  (new Thread(new MainActivity$$Lambda$0(this))).start();
}
// $FF: synthetic class
final class MainActivity$$Lambda$0 implements Runnable {
  private final MainActivity arg$1;
  MainActivity$$Lambda$0(MainActivity var1) {
    this.arg$1 = var1;
  }
  public void run() {
    this.arg$1.lambda$onCreate$0$MainActivity();
  }
}

原本的 lambda 靜態(tài)對象不再是靜態(tài)的了;lambda 類的構(gòu)造方法多了一個外部類對象的引用。因此,如果 lambda body 不是一個非純函數(shù),是有可能會造成內(nèi)存泄漏的(原因跟內(nèi)部類持有外部類對象是一樣)。
最后:附一篇官方介紹:https://developer.android.com/studio/write/java8-support.html

方法引用

這個就實在是讓我哭笑不得了。官網(wǎng)標注,Method References 完全支持了,原本想到kotlin 的高階函數(shù)會有性能問題,還想看看Java8會不會有這個問題。但是我用了一下,槽點滿滿。不管是Supplier還是Predicate,Function所有的方法調(diào)用都得要最低 API24,我靠現(xiàn)在普遍都是兼容到14的吧,你這讓我怎么用高階方法。不過我也嘗試不考慮低版本寫了一個,看了一下效果。

首先是Java8編譯前代碼:

public String str = "hello";
@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  test(() -> str);
}
public void test(Supplier<String> block) {
  System.out.println("=======" + block.get());
}

java8編譯后,貌似換湯不換藥,只替換lambda部分,方法內(nèi)依舊是普通對象方法調(diào)用:

protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  this.setContentView(2131296283);
  this.test(new MainActivity$$Lambda$0(this));
}
public void test(Supplier<String> block) {
  System.out.println("==========" + (String)block.get());
}
// $FF: synthetic class
final class MainActivity$$Lambda$0 implements Supplier {
  private final MainActivity arg$1;
  MainActivity$$Lambda$0(MainActivity var1) {
    this.arg$1 = var1;
  }
  public Object get() {
    return this.arg$1.lambda$onCreate$0$MainActivity();
  }
}

kotlin編譯前代碼:

val str: String = "hello"
override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  setContentView(R.layout.activity_main)
  test {
    str
  }
}
fun test(block: () -> String) {
  println("=========${block.invoke()}")
}

kotlin編譯后的代碼:

protected void onCreate(@Nullable Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView((int) R.layout.activity_main);
  test(new MainActivity$onCreate$1(this));
}
public final void test(@NotNull Function0<String> block) {
  Intrinsics.checkParameterIsNotNull(block, "block");
  System.out.println("=========" + ((String) block.invoke()));
}
/* compiled from: MainActivity.kt */
final class MainActivity$onCreate$1 extends Lambda implements Function0<String> {
  final /* synthetic */ MainActivity this$0;
  MainActivity$onCreate$1(MainActivity mainActivity) {
    this.this$0 = mainActivity;
    super(0);
  }
  @NotNull
  public final String invoke() {
    return this.this$0.getStr();
  }
}

所以說,kotlin在實現(xiàn)上跟Java也依舊是一模一樣,首先生成一個類,把lambda轉(zhuǎn)換成對象,再調(diào)用這個對象的invoke()方法。但是別忘了,kotlin有神奇的inline關鍵字,就專門用來解決這種莫名其妙的多生成一大堆對象的情況。
假設給上面的test()方法加上inline關鍵字后,編譯后的代碼就變成了這樣,相當于并沒有調(diào)用test()方法,因此也就不存在多生成的Function0對象了:

protected void onCreate(@Nullable Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView((int) R.layout.activity_main);
  MainActivity this_$iv = this;
  System.out.println("=========" + this.str);
}
public final void test(@NotNull Function0<String> block) {
  Intrinsics.checkParameterIsNotNull(block, "block");
  System.out.println("=========" + ((String) block.invoke()));
}

原本我是想夸一夸J8的支持,因為我最初以為他是將 lambda body 的純函數(shù)轉(zhuǎn)換成靜態(tài)方法,直接將 lambda 改成靜態(tài)方法調(diào)用來做的,結(jié)果沒想到還不如 kotlin。感覺就是 Google 為了 KPI 去加了一個 Java8 支持的噱頭。

相關文章

  • Android原生項目集成Flutter解決方案

    Android原生項目集成Flutter解決方案

    這篇文章主要介紹了Android原生項目集成Flutter解決方案,想了解Flutter的同學可以參考下
    2021-04-04
  • Android多種支付方式的實現(xiàn)示例

    Android多種支付方式的實現(xiàn)示例

    App的支付流程,添加多種支付方式,不同的支付方式,對應的操作不一樣,有的會跳轉(zhuǎn)到一個新的webview,有的會調(diào)用系統(tǒng)瀏覽器,有的會進去一個新的表單頁面,等等,本文就給大家詳細介紹一下Android 多種支付方式的優(yōu)雅實現(xiàn),需要的朋友可以參考下
    2023-09-09
  • Android PopupWindow使用實例

    Android PopupWindow使用實例

    這篇文章主要介紹了Android PopupWindow使用實例,本文直接給出代碼實例,需要的朋友可以參考下
    2015-06-06
  • 功能強大的登錄界面Android實現(xiàn)代碼

    功能強大的登錄界面Android實現(xiàn)代碼

    這篇文章主要為大家分享了功能強大的登錄界面Android實現(xiàn)代碼,驗證碼制作方法,自帶一鍵刪除功能,用戶名密碼為空時抖動提示效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • Android制作微信添加多個圖片放大圖片功能

    Android制作微信添加多個圖片放大圖片功能

    這篇文章主要介紹了Android制作微信添加多個圖片放大圖片功能,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2024-03-03
  • Android仿淘寶商品詳情頁效果

    Android仿淘寶商品詳情頁效果

    這篇文章主要為大家詳細介紹了Android仿淘寶商品詳情頁效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • Android RecyclerView的簡單使用

    Android RecyclerView的簡單使用

    這篇文章主要為大家詳細介紹了Android RecyclerView簡單使用的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • android 實現(xiàn)在照片上繪制涂鴉的方法

    android 實現(xiàn)在照片上繪制涂鴉的方法

    今天小編就為大家分享一篇android 實現(xiàn)在照片上繪制涂鴉的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-10-10
  • Android編程滑動效果之倒影效果實現(xiàn)方法(附demo源碼下載)

    Android編程滑動效果之倒影效果實現(xiàn)方法(附demo源碼下載)

    這篇文章主要介紹了Android編程滑動效果之倒影效果實現(xiàn)方法,基于繼承BaseAdapter自定義Gallery和ImageAdapter實現(xiàn)倒影的功能,并附帶demo源碼供讀者下載參考,需要的朋友可以參考下
    2016-02-02
  • Android利用RecyclerView實現(xiàn)列表倒計時效果

    Android利用RecyclerView實現(xiàn)列表倒計時效果

    這篇文章主要為大家詳細介紹了Android利用RecyclerView實現(xiàn)列表倒計時效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-09-09

最新評論