AS3.0中的J8新特性

今天google官方放出了期待已久的AS3.0正式版,加入了很多新特性,支持kotlin,java8,编译速度更快等等,想必很多kotlin小迷弟,小迷妹们已经欢呼雀跃。然鹅,菜鸡如我,不会使用kotlin。只能研究一下作为android开发者在AS3.0中可以使用到的java8新特性。

官方对于AS中J8新特性的页面如下Use Java 8 Language Features(请自备红杏)

附上gradle-4.1-all.zip地址

配置Java8

首先需要抛弃之前的第三方插件

Android Studio为使用某些Java 8语言功能和使用它们的第三方库提供内置支持。,默认工具链通过desugar在javac编译器的输出上执行字节码转换来实现新的语言特性。

默认工具链

在3.0之前,相信很多小伙伴为了尝试java8的新特性,会使用第三方的插件来使用lambda,如:Jack, Retrolambda, 或 DexGuard,AS3.0将对其不再提供支持,如果as检测到你继续使用这些插件,as将继续使用第三方插件,而不使用默认的工具链。

删除Jack支持

jackOptionsbuild.gradle删除

  android {
      ...
      defaultConfig {
      ...
    // 删除此代码块
        jackOptions {
            enabled true
              ...
        }
}

删除Retrolambda

请从项目级build.gradle文件中删除Retrolambda依赖关系

buildscript {
  ...
   dependencies {
      // 删除此依赖
      classpath 'me.tatarka:gradle-retrolambda:<version_number>'
   }
}

并删除每个moudle下的build.gradle文件中Retrolambda引入

//删除
apply plugin: 'me.tatarka.retrolambda'
//删除(如果有的话)
retrolambda {
    jvmArgs '-Xmx2048m'
}

设置Java8

build.gradle文件下android节点添加如下

android {
  ...
  //将项目的源和目标兼容性值设置为Java 8
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

AS中的Java8新特性

放一张官方的资料图:

image.png

可以看到新版AS中指支持部分Java8的新特性,且有一部分还有minSdkVersion限制。接下来,我们对其比较常用的进行讲解:

Lambda

相信大家已经lambda已经非常熟悉,这里我们不讲语法,讲点别的需要注意的地方。

与匿名内部类的区别

lambda大家看作是一种匿名内部类,但实际却与匿名内部类是有区别的,

  • lambda编译完成之后,使用的是J7新增的指令invokedynamic来表示,具体的实现不体现在字节码文件中,由虚拟机进行翻译lambda的具体执行策略,以便于后续JDK版本优化此语法特性的策略,同时可以很大程度上减少字节码的文件的大小和数量,分配方式类似于java.lang.invokeMethodHandle中的动态调用方法(具体请百度)。目前lambda的具体执行方式还是与匿名内部类差不多的策略,据说oracle在以后的版本更新中会优化分配测罗,选用MethodHandle
  • 而匿名内部类方式生成新类,新建一个标有$xx.class的文件。

分类

lambda表达式的类型是一种特殊的接口,这种接口只有一个抽象方法,成为函数接口。

在J8中,lambda表达式倾向于函数式编程,根据其输入与返回类型不同,分为几种类型的函数接口,下面是系统提供的一组函数式接口类型,并以Rxjava的操作符举例:

接口 参数 返回类型 说明
Predicate<T> T boolean 判断型函数,filter
Consumer<T> T void 消费型函数,subcribe
Function<T,R> T R 转换型函数,map
Supplier<T> None T 生产型函数,create
UnaryOperator<T> T T Function的特殊情况
BinaryOperator<T> (T,T) T (二元)多元运算,zip

我们可以同过自定义接口进行使用,如android的View.OnclickListener极为消费性函数。

注意,在自定义函数接口时,站在用途的角度来考虑,为了区分普通接口与函数接口的区别,建议自定的函数接口都应该加上@FunctionalInterface注解。该直接会强制编译器检查一个接口是否符合函数接口的标准。如果该注释添加给一个枚举类型,类或者接口包含不止一个抽象方法,编译器就会报错。这对我们规范化代码有很大的帮助。

重载解析

,在运行过程中,会根据,java中可以重载方法,造成多个方法会有相同的方法名,但签名却不一样。这在推断类型是会带来问题,因为系统可能会推断出多种方法类型。当lambda表达式作为参数时,当出现重载情况时,这时,

java会挑出最具体的类型。

看一个例子:

static interface IntergerBifunciton extends BinaryOperator<Integer>{
    }
    public  void overloadedMethoe(BinaryOperator<Integer> l){
    }
    public  void overloadedMethoe(IntergerBifunciton l){
    }

接口IntergerBifuncitonBinaryOperator的子接口,在调用overloadedMethoe((x,y)->x+y)的时候,虚拟机会选用最具体的类型

再看一个无法推断哪个更具体类型的例子:

    static interface Intergerfunciton{
        public boolean test(int x);
    }
    public  void overloadedMethoe(Predicate<Integer> l){
    }
    public  void overloadedMethoe(Intergerfunciton l){
    }

我们使用overloadedMethoe((x)->true);调用的时候,会出现错误:

模糊调用

这是因为,编译器无法推断出哪种类型更具体 更适合方法的参数,故报错。我们在日常开发中应该避免出现这种情况。

Default and static interface methods(默认方法和静态接口方法)

  • 默认方法
    java8相比之前最大的改动无疑是对集合类的改动和添加StreamAPI(minSdkVersion为24可用),用于在集合类中更方便的进行函数是编程,大家可以把StreamAPI看成类似Rxjava的类库,用以方便的对数据进行变换。(同样的,Stream也有很多类似Rxjava操作符的方法,比如filter,map,toList,flatmap等等,使用方法大同小异)。

java为Collection接口添加了stream方法(见下图),但是问题出现了,这意味着java1-java7中,实现了Collection接口的全部类都需要实现stream方法,否则,那些类将无法在java8里面通过编译。java为了保持向下兼容性,java8引入了默认方法,用关键字default表示。形象化说法就是:Collection告诉他的子类,如果你没有实现stream方法,就用我的吧。

stream方法

我们可以看到,在j8中,很多地方都使用了默认方法,如Iterable接口中的forEachspliterator

子接口中或者实现类中实现覆盖默认方法,需要Override注解。

看一下默认方法在复杂的继承关系中的一种特殊情况:


image.png

如图,OverrideChild既实现了Parent接口,又继承了实现了Parent接口的类,那么调用时,应该调用哪个方法呢?此例子打印出来的是from ParentImpl,原因在于,与接口中定义的默认方法相比,类中重写的方法更具体

调用优先级为:类重写方法>子接口重写方法>父接口方法

接口允许多继承,因此,有了默认方法,子类就可以继承多个接口中的默认实现。这在某种形式上实现了多重继承的功能。(注意:如果在继承的多个接口中,有多个签名相同的默认方法,编译器将报错)

  • 接口的静态方法

在以往的jdk版本中,接口是不允许存在静态方法的,j8发布后,为了使Stream.of静态方法,加入了静态方法,使得同一接口的子类可以共享这一静态方法。

try-with-resources

AS3.0在所有android api层面对try-with-resources进行支持。

try-with-resources声明一个或多个资源的 try 语句。一个资源作为一个对象,必须在程序结束之后随之关闭。 try-with-resources语句确保在语句的最后每个资源都被关闭 。

任何实现了 java.lang.AutoCloseable的对象, 包括所有实现了 java.io.Closeable 的对象, 都可以用作一个资源。

先来一段代码:

image.png

可以看到, try-with-resources 语句声明的资源是一个 BufferedReader。声明语句在紧跟在 try 关键字的括号里面。在j8之前,如果我要是有一个资源,在使用之后,需要显示的效用其close方法将其关闭,但j8新的语法糖出现后,我们只需要将其声明在try中,在资源使用完毕之后,将自动关闭,不需要手动调用。上面的语句相当于:

image.png

我们可以在try后声明多个资源,见下图:

image.png

我们也可以在try-with-resources 语句后添加自己需要捕获的异常或添加finally语句块,如下图:

image.png

注意,在try-with-resources 语句中, 任意的 catch 或者 finally 块都是在声明的资源被关闭以后才运行。

如果try-with-resources语句中资源的Close方法和try代码块中都抛出了异常,Close 方法抛出的异常被抑制,try代码块中的异常会被抛出。
Java7之后,可以使用Throwable.getSuppressed方法获得被抑制的异常。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容