最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

AndroidStudio3 支持 Java8 了請(qǐng)問(wèn)你敢用嗎

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

摘要: 今天早上,Google 發(fā)布了 AS 3.0,以及一系列的 Support 包,有意思的新東西挺多,因?yàn)橹耙恢痹诳?kotlin的支持,特地翻了一下對(duì) Java8 的支持方式,結(jié)果……

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

支持 Java 8

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

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

官網(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 會(huì)對(duì) class 做操作,將內(nèi)部的lambda相關(guān)的語(yǔ)法轉(zhuǎn)換為dalvik可識(shí)別的語(yǔ)法。
說(shuō)的太抽象具體表現(xiàn)我們看代碼。

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

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

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();其實(shí)這一句就是原本lambda body,他被轉(zhuǎn)換成了 MainActivity 類(lèi)中的一個(gè) static method。在最終編譯成 dex 后會(huì)再次優(yōu)化,減少一次方法調(diào)用直接變成run方法的body(相當(dāng)于內(nèi)聯(lián))。具體原理操作請(qǐng)見(jiàn)源碼的visitInvokeDynamicInsn方法:GoogleCode請(qǐng)自備梯子

上面的代碼演示了純函數(shù)(什么是純函數(shù)自己wiki)的操作,下面看一個(gè)非純函數(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)對(duì)象不再是靜態(tài)的了;lambda 類(lèi)的構(gòu)造方法多了一個(gè)外部類(lèi)對(duì)象的引用。因此,如果 lambda body 不是一個(gè)非純函數(shù),是有可能會(huì)造成內(nèi)存泄漏的(原因跟內(nèi)部類(lèi)持有外部類(lèi)對(duì)象是一樣)。
最后:附一篇官方介紹:https://developer.android.com/studio/write/java8-support.html

方法引用

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

首先是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)依舊是普通對(duì)象方法調(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();
  }
}

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

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的支持,因?yàn)槲易畛跻詾樗菍?lambda body 的純函數(shù)轉(zhuǎn)換成靜態(tài)方法,直接將 lambda 改成靜態(tài)方法調(diào)用來(lái)做的,結(jié)果沒(méi)想到還不如 kotlin。感覺(jué)就是 Google 為了 KPI 去加了一個(gè) Java8 支持的噱頭。

相關(guān)文章

  • Android ProgressBar 模擬進(jìn)度條效果的實(shí)現(xiàn)

    Android ProgressBar 模擬進(jìn)度條效果的實(shí)現(xiàn)

    這篇文章主要介紹了Android ProgressBar 模擬進(jìn)度條效果的實(shí)現(xiàn),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • Android Studio 3.6 layout文件text模式切換問(wèn)題

    Android Studio 3.6 layout文件text模式切換問(wèn)題

    這篇文章主要介紹了Android Studio 3.6 layout文件text模式切換問(wèn),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-03-03
  • android開(kāi)發(fā)設(shè)計(jì)模式之——單例模式詳解

    android開(kāi)發(fā)設(shè)計(jì)模式之——單例模式詳解

    本篇文章主要介紹了android開(kāi)發(fā)設(shè)計(jì)模式之——單例模式詳解,具有一定的參考價(jià)值,有需要的可以了解一下。
    2016-11-11
  • Android JNI處理圖片實(shí)現(xiàn)黑白濾鏡的方法

    Android JNI處理圖片實(shí)現(xiàn)黑白濾鏡的方法

    這篇文章主要介紹了Android JNI處理圖片實(shí)現(xiàn)黑白濾鏡的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01
  • Android自定義View制作儀表盤(pán)界面

    Android自定義View制作儀表盤(pán)界面

    這篇文章主要介紹了Android自定義View制作儀表盤(pán)界面的相關(guān)資料,首先需要自定義儀表盤(pán)的屬性,在構(gòu)造方法種獲取自定義屬性,本文介紹的非常詳細(xì),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-11-11
  • Android開(kāi)發(fā)使用自定義view實(shí)現(xiàn)ListView下拉的視差特效功能

    Android開(kāi)發(fā)使用自定義view實(shí)現(xiàn)ListView下拉的視差特效功能

    這篇文章主要介紹了Android開(kāi)發(fā)使用自定義view實(shí)現(xiàn)ListView下拉的視差特效功能,結(jié)合實(shí)例形式詳細(xì)分析了Android重寫(xiě)ListView控件實(shí)現(xiàn)ListView下拉視差效果的步驟與相關(guān)操作技巧,需要的朋友可以參考下
    2017-10-10
  • Android+Html5混合開(kāi)發(fā)仿微信朋友圈

    Android+Html5混合開(kāi)發(fā)仿微信朋友圈

    這篇文章主要為大家詳細(xì)介紹了Android+Html5混合開(kāi)發(fā)仿微信朋友圈的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • 詳解Android數(shù)據(jù)存儲(chǔ)之SQLCipher數(shù)據(jù)庫(kù)加密

    詳解Android數(shù)據(jù)存儲(chǔ)之SQLCipher數(shù)據(jù)庫(kù)加密

    對(duì)于已經(jīng)ROOT的手機(jī)來(lái)說(shuō)的沒(méi)有任何安全性可以,一旦被利用將會(huì)導(dǎo)致數(shù)據(jù)庫(kù)數(shù)據(jù)的泄漏,本篇文章主要介紹了Android數(shù)據(jù)存儲(chǔ)之SQLCipher數(shù)據(jù)庫(kù)加密,具有一定的參考價(jià)值,有需要的可以了解一下。
    2016-12-12
  • Android中刪除Preference詳解

    Android中刪除Preference詳解

    這篇文章主要介紹了Android中刪除Preference詳解,很多時(shí)候刪除Preference總會(huì)失敗,本文著重分析刪除失敗的原因,需要的朋友可以參考下
    2015-01-01
  • Android手機(jī)管理工具類(lèi)詳解

    Android手機(jī)管理工具類(lèi)詳解

    這篇文章主要為大家詳細(xì)介紹了Android手機(jī)管理工具類(lèi),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08

最新評(píng)論

涟水县| 桐梓县| 定日县| 垣曲县| 岑巩县| 宝鸡市| 贵南县| 舟曲县| 万山特区| 盐山县| 潮安县| 石棉县| 万宁市| 大名县| 竹北市| 平利县| 防城港市| 白朗县| 洪江市| 伽师县| 绿春县| 文登市| 中方县| 松阳县| 中超| 洪雅县| 黄冈市| 凤台县| 尚志市| 临潭县| 虞城县| 红安县| 灵石县| 阿鲁科尔沁旗| 封丘县| 达尔| 洛阳市| 青海省| 广德县| 西畴县| 孝义市|