改变习惯的关键在于,在维持原先的暗示信号和奖赏的同时,以新的惯例行为代替旧的惯例行为。
翻译自:Use Java 8 language features
简介
公告:Jack toolchain目前已经被弃用了。您可以继续使用它,或者尝试使用Android Studio最新的版本来使用Java 8的新特性。
Android支持所有的Java 7的特性和部分的Java8的新特性。这篇文章介绍你可以使用的Java 8的特性,以及如何正确的配置您的项目来使用新特性和您可能遇到的一直的问题。
注意:在开发Android程序的时候,编译的JDK版本是可选的。您可以使用Java 8来编译为了保证项目的源和目标的兼容性而单单采用了Java7特性的项目。
这篇文章介绍如何使用名为Jack的编译器(仅适用于Android Studio 2.1及更高版本)启用对Java 8语言特性的支持。
如果你已经安装了Android Studio的话,请保证您的AS是最新的版本(可以使用Help > Check for Update
(在Mac中, Android Studio > Check for Updates
))。如果您尚未安装的话,那么为您的系统安装[Android Studio](Android Studio > Check for Updates)。
支持Java 8的语言特性和API接口
遗憾的是,Android并非支持所有的Java 8的语言特性(部分支持),但是开发面向Android 7.0的应用程序的时候,可以使用以下的功能:
注意:类型注释在编译时是可以用的,但是在运行时不可用。此外,该平台支持API24以及更低版本的TYPE,但是不支持
ElementType.TYPE_USE
或者ElementType.TYPE_PARAMETER
。
为了测试可不可以在更低版本上的Android进行使用lambda表达式,方法引用和类型注解,请到你的项目根目录下的build.gradle
中,设置compileSdkVersion
和targetSdkVersion
为23或者是更低的版本。你需要启用enable the Jack toolchain
来始终支持Java 8的特性。此外,以下的Java 8的API接口是可用的:
- Reflection(反射)和 language-related 的APIs:
- Utility APIs:
启用Java 8特性和Jack Toolchain
为了使用Java 8 语言特性,你需要使用Jack toolchain。这个Android工具链将Java语言源编译为Android可读的DEX字节码,具有自己的.jack库格式,并提供大多数工具链功能。作为单一工具的一部分,它具有重新打包,压缩体积,混淆代码和multidex的功能。
以下是用于构建Android DEX文件的两个工具链的比较:
- 常规的javac工具链:
javac (.java → .class) → dx (.class → .dex)
- 新的Jack工具链:
ack (.java → .jack → .dex)
Gradle配置
为了在您的项目中启用Java 8的语言特性和Jack工具链,你需要打开build.gradle
,添加以下内容:
android {
...
defaultConfig {
...
jackOptions {
enabled true
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
已知的issues
安装运行的时候Jack工具链并没有运行,而且会在启用新的工具链的时候被禁用:
因为Jack工具链在编译应用程序的时候不会生成中间类文件,所以依赖这些文件的工具目前是不能与Jack工具链公用的。这些工具的一些例子是:
- 针对类的Lint语法检测器
- 需要应用程序类文件的工具和库(比如JaCoCo这类的测试工具)
lambda在Android中的应用
Lambda 表达式,也被称为闭包,是为开发者提供用简单和紧凑的方式表示数据的匿名函数。
Brian Goetz, Specification Lead for JSR 335
- android lambda的使用总结及运行原理
- Lambda表达式的意义
- 对程序员来说最直观的感受就是用Lambda表达式可以简化很多代码。使用它可以很轻松的将很多行代码缩减成一行。
- 而更大的意义是,Lambda表达式对java性能的提升。
- Java 8 Lambda 表达式示例
什么时候使用Lambda表达式
Lambda表达式并不是匿名内部类的替代者,而是一个用来实现单一抽象方法的更好的方式。两者都有自己的意义,并在各自特定的情况下使用。
Lambda 表达式用来实现单一的行为,并且该行为要被传递个其他的代码。
当只需要一个功能接口的简单实例,而不需要类型,构造方法和一些相关的东西时,Lambda表达式比较适用。
另一方面,只在需要新的字段和功能时使用匿名内部类。
Lambda表达式和匿名内部类
匿名内部类会引入下一级作用域,而lambda表达式不会。在匿名内部类中可以出现和父类中相同名字的变量,但这在lambda表达式中会报错,并且不允许这样做。因为后者不会引入下一级作用域,并且父级作用域中的局部变量和方法可以被直接访问。
匿名内部类把 this 关键字作为它自身的对象,而lambda表达式把它当成是该表达式所在类的对象。在表达式所在的类中,你可以通过使用 this 来访问lambda表达式中的变量。
但是,像匿名内部类那样,lambda表达式只能访问所在类中用final修饰的变量。同样的,如果要访问非final修饰的变量则会报错。
只有当lambda表达式的参数和返回值都是Serializable类型时才允许将其序列化。就像不推荐序列化匿名内部类一样,我们也不推荐序列化lambda表达式。
Lambda表达式被编译成其所在类的私有方法。java 7中引入的invoke dynamic
被用来动态的绑定方法。
Lambda表达式取代了匿名类,取消了模板,允许用函数式风格编写代码。这样有时可读性更好,表达更清晰。在Java生态系统中,函数式表达与对面向对象的全面支持是个激动人心的进步。将进一步促进并行第三方库的发展,充分利用多核CPU。