在 Android N 预览版中使用 Java 8 的新特性

简介: 本文讲的是在 Android N 预览版中使用 Java 8 的新特性,在这篇文章中,去介绍Oracle Java 8的新特性并没有太大意义 —— 很多信息已经在互联网上有了。我个人最喜欢的是Simon Ritter的“Java SE 8的55个新特性[2]”。
本文讲的是在 Android N 预览版中使用 Java 8 的新特性,

Android团队最近发布了Android N Preview,带来了很多提升,包括由Jack编译器提供的Java 8支持。在这篇文章中,我们将来看看它究竟对Android开发者意味着什么,以及如何尝试新的语言特性。

免责声明: 本信息在2016年3月30日是有效的,我不确定在下个release版本中,Google团队会增加什么新的没有在此提到的Java 8特性。

概览

在这篇文章中,去介绍Oracle Java 8的新特性并没有太大意义 —— 很多信息已经在互联网上有了。我个人最喜欢的是Simon Ritter的“Java SE 8的55个新特性[2]”。

另一方面,Android 官方的Java 8公告[3] 留下了很多开放的问题给开发者们,感觉上并非所有的原生 Java 8 功能都是可用的。更详细的 技术公告[4] 确认了这一点。我们可以根据在 Android N 中的可用性,将这些语言特性分类如下:

Android Gingebread (API 9)及以上:

Android N及以上:

所以对Java 8特性和使用的minSdkVersion之间的关联性,开发者必须去精心选择。我们也必须注意到语言向后兼容是由Jack编译器提供的。在概念上,Jack编译器将javac,ProGuard,以及dex的功能 合并 [5]到了一个转换步骤中。这意味着[6]其中没有中间的Java字节码可用,且像是JaCoCo和Mockito的工具将无法工作,DexGuard也一样 (ProGuard的企业版本)。让我们祈祷这只是一个早期的preview版本,且这些问题将在未来被修复。

Lambda表达式以及相关的函数功能APIs —— 这是一个每个Android开发都会喜欢的东西。这类功能将会对增加代码可读性极为有用 —— 它替代了提供事件监听器的匿名内部类。而之前只能通过 额外的工具[7] 来实现,或者由Android Studio编辑器去折叠代码。

默认及静态interface方法可以帮助我们减少额外的工具类的数量,但显然不是最需要的特性。还有一些其他的新增功能,我希望去说的更详细一些,因此不在本文的范围内。

对我来说最有趣的事 —— Java 8 流(Streams) —— 在当前的预览版中不可用。我们可以发现事实上它 刚被merge[8] 到AOSP源码,所以期望可以在下个N Preview 或者 Beta release中见到它。如果你实在等不及去浏览 —— 可以试试使用 Lightweight-Stream-API[9],目前的一个开源向后兼容。

示例项目

官方手册[10]提供了指示,甚至还有图展示了如何去配置你的项目使用 Android N Preview 和 Java 8。在这儿没什么可以再说的,就跟着指示走吧。

下一步是去配置你的app模块的 build.gradle 文件。你可以在下面看到实例的 build.gradle 文件。从N SDK上的公告来看,似乎可以设置 minSdkVersion 为 Jelly Bean 或者 KitKat。 但… 在将 targetSdkVersion 设为Android N Preview后,将无法工作在API低于N的设备上[11]。另外,如果你把 minSdkVersion 设置为23或者更低 —— Java 8代码将无法编译。这里是一些在SO forums[12]的hack,描述了怎么设置minSdk为想要的值并使得app可以工作。我希望你不会在生产代码中使用这种方法 :)

我决定保持实例代码干净,所以没有添加任何hack手段来做低版本兼容,请读者自由去尝试或者使用N的测试设备/模拟器。


       
       
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

       
       
android {
compileSdkVersion 'android-N'
buildToolsVersion '24.0.0 rc1'
defaultConfig {
applicationId "org.sergiiz.thermometer"
minSdkVersion 'N' // 在 N Preview 中不能使用低于N的版本
targetSdkVersion 'N'
versionCode 1
versionName "1.0"
jackOptions{
enabled true
}
}
compileOptions {
targetCompatibility 1.8
sourceCompatibility 1.8
}
//...
}

请注意这个设置是跟着新的文档[13]来的,使用了新的 Gradle DSL 方法 jackOptions 来配置Jack编译器设置,在更老的版本中,我们使用 useJack true 来达到同样的结果。

所以来试着实现一些Java 8的优雅代码到我们陈旧的Thermometer项目。

这是一个接口,包含了默认方法:


       
       
1
2
3
4
5
6
7
8
9
10
11
12
13

       
       
public interface Thermometer {
void setCelsius(final float celsiusValue);
float getValue();
String getSign();
default String getFormattedValue(){
return String.format(Locale.getDefault(),
"The temperature is %.2f %s", getValue(), getSign());
}
}

实现了这个接口的类:


       
       
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

       
       
public class FahrenheitThermometer implements Thermometer {
private float fahrenheitDeg;
public FahrenheitThermometer(float celsius) {
setCelsius(celsius);
}
@Override
public void setCelsius(float celsius) {
fahrenheitDeg = celsius * 9 / 5 + 32f;
}
@Override
public float getValue() {
return fahrenheitDeg;
}
@Override
public String getSign() {
return Constants.DEGREE + "F";
}
}

增加一个点击事件的lambda函数:


       
       
1
2
3
4
5

       
       
buttonFahrenheit.setOnClickListener(view1 -> {
fahrenheitThermometer.setCelsius(currentCelsius);
String text = fahrenheitThermometer.getFormattedValue();
makeText(MainActivity.this, text, Toast.LENGTH_SHORT).show();
});

例子的完整源码可见 GitHub repository[14]

总结

在这篇文章中,我们了解了Java 8的用例,以及目前其在Android N Preview SDK的实现情况。我们也看到了当前Jack编译器的限制,及其在最后发布前可能被修复的功能。在demo项目中我们检验了如何去使用新的Java 8特性,以及它们可以被应用的target SDK版本。





原文发布时间为:2016年04月20日

本文来自云栖社区合作伙伴掘金,了解相关信息可以关注掘金网站。
目录
相关文章
|
23天前
|
存储 安全 Java
Java Map新玩法:探索HashMap和TreeMap的高级特性,让你的代码更强大!
【10月更文挑战第17天】Java Map新玩法:探索HashMap和TreeMap的高级特性,让你的代码更强大!
50 2
|
24天前
|
存储 Java
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
34 3
|
24天前
|
存储 Java 数据处理
Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位
【10月更文挑战第16天】Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位。本文通过快速去重和高效查找两个案例,展示了Set如何简化数据处理流程,提升代码效率。使用HashSet可轻松实现数据去重,而contains方法则提供了快速查找的功能,彰显了Set在处理大量数据时的优势。
31 2
|
26天前
|
存储 算法 Java
Java Set因其“无重复”特性在集合框架中独树一帜
【10月更文挑战第14天】Java Set因其“无重复”特性在集合框架中独树一帜。本文深入解析Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定的数据结构(哈希表、红黑树)确保元素唯一性,并提供最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的`hashCode()`与`equals()`方法。
27 3
|
30天前
|
安全 Java API
Java 17新特性让你的代码起飞!
【10月更文挑战第4天】自Java 8发布以来,Java语言经历了多次重大更新,每一次都引入了令人兴奋的新特性,极大地提升了开发效率和代码质量。本文将带你从Java 8一路走到Java 17,探索那些能让你的代码起飞的关键特性。
75 1
|
1月前
|
编解码 Oracle Java
java9到java17的新特性学习--github新项目
本文宣布了一个名为"JavaLearnNote"的新GitHub项目,该项目旨在帮助Java开发者深入理解和掌握从Java 9到Java 17的每个版本的关键新特性,并通过实战演示、社区支持和持续更新来促进学习。
75 3
|
6天前
|
分布式计算 Java API
Java 8引入了流处理和函数式编程两大新特性
Java 8引入了流处理和函数式编程两大新特性。流处理提供了一种声明式的数据处理方式,使代码更简洁易读;函数式编程通过Lambda表达式和函数式接口,简化了代码书写,提高了灵活性。此外,Java 8还引入了Optional类、新的日期时间API等,进一步增强了编程能力。这些新特性使开发者能够编写更高效、更清晰的代码。
17 4
|
21天前
|
存储 Java API
优雅地使用Java Map,通过掌握其高级特性和技巧,让代码更简洁。
【10月更文挑战第19天】本文介绍了如何优雅地使用Java Map,通过掌握其高级特性和技巧,让代码更简洁。内容包括Map的初始化、使用Stream API处理Map、利用merge方法、使用ComputeIfAbsent和ComputeIfPresent,以及Map的默认方法。这些技巧不仅提高了代码的可读性和维护性,还提升了开发效率。
41 3
|
21天前
|
存储 安全 Java
Java Map新玩法:深入探讨HashMap和TreeMap的高级特性
【10月更文挑战第19天】Java Map新玩法:深入探讨HashMap和TreeMap的高级特性,包括初始容量与加载因子的优化、高效的遍历方法、线程安全性处理以及TreeMap的自然排序、自定义排序、范围查询等功能,助你提升代码性能与灵活性。
23 2
|
27天前
|
Java 开发者
在Java的集合世界里,Set以其独特的特性脱颖而出,它通过“哈希魔法”和“红黑树防御”两大绝技
【10月更文挑战第13天】在Java的集合世界里,Set以其独特的特性脱颖而出。它通过“哈希魔法”和“红黑树防御”两大绝技,有效抵御重复元素的侵扰,确保集合的纯洁性和有序性。无论是“人海战术”还是“偷梁换柱”,Set都能从容应对,成为开发者手中不可或缺的利器。
30 6