JAVA8新特性在Android编程的实践研究(一)

前言

其实Java8已经出现了很久,听闻Java9都准备出了,但是现在普及率并不不是很高,主流的开发环境依然是Java7,甚至有些依然在使用Java5等比较老旧的开发环境。作为一名Android开发者,Java是我们的主要开发语言,我们还是很有必要去了解并且使用最新型的技术,而且Java8中有许多新的特性也是有利于提高我们开发效率的,下面我来一一介绍一下。

本文参考了很多网络上已有的文章,且已注明出处。

介绍

在Android编程中使用Java8新特性,需要先在Android studio中配置一下,具体配置方法,可参考此配置

接口默认方法

在java8中,接口可以添加默认的方法以及静态方法,其类型也是public abstract的类型,实现方式如下:

public interface DataSource<T> {

    List<T> reqeustData(String name);

    @RequiresApi(api = Build.VERSION_CODES.N)
    default void defaultMethod() {
        Log.i("DataSource", "i am defaultMethod");
    }
    
    static void staticMethod(){
        Log.i("DataSource", "i am staticMethod");
    }
}

需要注意的是,接口默认方法现在只能在Android N以上才支持,所以使用的时候要添加声明。

相比于传统的接口,我们在Java8中可以添加默认的方法,而这个默认方法的类型同样是public 的,所以我们可以把它当做正常方式使用,只是无需去实现。在实际项目当中,当一个接口被多个类实现时,我们去拓展接口里面的方法时会导致工程量变大,而当我们引入接口默认方法时,就无需去修改每个类。

当一个接口扩展另外一个包含默认方法的接口的时候,有以下3种处理方式。

  • 完全无视默认方法
    直接继承了上级接口的默认方法
  • 重新申明默认方法
    重新把默认方法申明为抽象方法(无实现,具体子类必需再次实现该方法)
  • 重新实现默认方法
    重写了默认方法的实现,依然是一个默认方法。

我觉得如果对访问权限没有特别要求的,接口基本上能够代替抽象类,而且还能实现多继承。如果对抽象类和接口默认方法感兴趣的童鞋,可以参考这篇文章Java 8 之默认方法(Default Methods)

Lambda表达式

Lambda表达式又称为闭包或匿名方法,我觉得lambda表示式式Java8中最受欢迎的一个特性,因为只要用习惯了这个表达式,就不会再想去用旧的方法来实现了。

Lambda表达式我相信很多人已经听说过,所以我就不做过多介绍,主要说一下我在Android开发中使用到的一些场景:

        button.setOnClickListener(v->showLog("hello"));
        new Thread(()->showLog("hello")).start();
        //多个参数的写法
        List<String> names = Arrays.asList("nickming", "peter", "mike");
        Collections.sort(names, (a, b) -> b.compareTo(a));
        names.forEach(this::showLog);

当然,这只是lambda运用的一部分示例,总结起来lambda的作用就是:

  • 简化代码,可以不用再写匿名内部类,可以将多行代码简化为一行代码。
  • 提供函数式接口,实现函数式编程
  • 提升Java性能

强烈建议在编程中多使用lambda表达式,特别是配合RxJava以及RxAndroid的使用,写起代码真的是行云流水一气呵成。感兴趣的童鞋可以参考这篇文章Lambda表达式的意义

但是使用lambda表达式需要注意几点:

  • 在lambda表达式中可以直接访问外层final变量、实例、静态变量。
  • 访问未标记final的变量时,该变量会具有隐形final属性,如果后续更改变量值,会导致编译不通过。
  • 在lambda表达式中,对于内部实例和静态变量可读可写。
  • lambda无法访问到接口的默认方法。

函数式接口

“函数式接口”是指仅仅只包含一个抽象方法的接口,每一个该类型的lambda表达式都会被匹配到这个抽象方法。因为 默认方法 不算抽象方法,所以你也可以给你的函数式接口添加默认方法。

@FunctionalInterface
public interface Converter<F,T> {
    T convert(F from);
}

Converter<Integer,String> converter= (f)->String.valueOf(f);
converter.convert(1);

Converter<String,Integer> converter3=Integer::new;
Converter<String,Integer> converter2=Integer::valueOf;

这是我们自定义的函数式接口,其实在Java8中已经给很多接口都预置了FunctionalInterface这个关键字,所以这是Java8支持函数式编程的一个重要原因之一,像Runnable、Comparator等接口在Java8中都是标记有FunctionalInterface关键字的。感兴趣的童鞋可以参考这篇文章函数式接口

由于是函数式编程,在我个人理解就是将函数当做编程的基础,区别于我们之前的面向对象的编程,我们所有操作都以函数为基础,函数可以当做其他函数的变量参数,也可以当做其他函数的返回结果。

既然Java8支持函数式编程,所以其提供了方法与构造函数引用这个方式,就像我们可以直接通过Integer::new来实现converter,new是直接实现integer的构造函数,valueOf是其方法引用,只要其返回结果是接口需要实现的返回类型即可。

其实在许多场景下,我们可以直接利用 :: 这个符号来实现方法的引用,例如上文提到的

names.forEach(this::showLog)

这一行代码中,我们省略了for循环,实际上forEach函数式stream特性的一个,下文会提到。forEach函数需要实现Consumer接口,接着在实现其accept方法:

        names.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                showLog(s);
            }
        });
        //lambda表达式
        names.forEach(s->showLog(s));
        //方法引用
        names.forEach(this::showLog);

直接组合利用lambda表达式和方法引用,可以简化代码,表达值简单明了。

常见的函数接口

Java8实际上提供了很多常用的函数式接口,都位于package java.util.function包下面,常用的如下:

  • Predicate 接口只有一个参数,返回boolean类型。该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如:与,或,非)
  • **Function **接口有一个参数并且返回一个结果,并附带了一些可以和其他函数组合的默认方法(compose, andThen)
  • **Supplier **接口返回一个任意范型的值,和Function接口不同的是该接口没有任何参数
  • **Consumer **接口表示执行在单个参数上的操作
  • **Comparator **是老Java中的经典接口, Java 8在此之上添加了多种默认方法
  • **Optional **被定义为一个简单的容器,其值可能是null或者不是null。在Java 8之前一般某个函数应该返回非空对象但是偶尔却可能返回了null,而在Java 8中,不推荐你返回null而是返回Optional

我就不仔细分析每个接口的作用了,主要参考函数式接口这篇文章。

其实,当你尝试过使用RxJava和RxAndroid后,你会发现这些x里面的很多概念都是做法都是和Java8中很相似的,都是提供了各种函数操作符,各种函数接口实现。

小结

在这篇文章中,主要是介绍了一下接口默认方法、lambda表达式、函数式接口、方法构造函数的引用这几个特性,在下一篇文章中会着重介绍一下streamDate APIAnnotationCompletableFuture几个特性。

JAVA8新特性在Android编程的实践研究(二)

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

推荐阅读更多精彩内容