不服来战,看 Kotlin 如何完爆 Java
点击上方“CSDN”,选择“置顶公众号”
关键时刻,第一时间送达!
Java 是第一个用于移动应用程序开发的编程语言,但现在你可以使用不同的编程语言(包括 C#,C / C ++,JavaScript 和 Scala)开发 Android 应用程序。
Kotlin 在今年得到了广泛的关注,在 Google I / O 大会上,Google 正式发布了 Kotlin 编程语言用于 Android 应用开发。
接下来,本文将以图表的形式区分 Kotlin 和 Java 之间一些重要的不同点,并深度剖析 Kotlin 作为后起之秀如何解决 Java 的诸多痛点。
Android 编程语言之争:Kotlin VS Java
Java 是 Android 开发完美的解决方案?
在开发领域,很多人产生如何区别开发 Android 应用程序与其他领域开发的疑问?
而以原生方式在不同硬件上执行相同应用程序可能会是其中原因之一。但这怎么可能?下面笔者将通过解释 Kotlin 语言的好处来继续这篇文章。
在这一点上,没有人惊讶地看到相同的 Web 应用程序运行于任何设备,任何平台(Android、iOS、 Windows、MacOS…)。我们都知道这些应用程序比任何本地应用程序都更慢,也更不稳定,但是优点是,我们只需要为所有平台开发一个应用程序。Java 的强悍之处在于如今它已经应用于数十亿的设备上,无论其硬件和软件如何,只要它有一个 Java 编译器生成的 pseudo-compiled 解释器。
但是,这是否意味着 Java 是完美的解决方案?不幸的是,事实并非如此。尽管 Java 解决了设备之间的互操作性问题,但它带来了一系列新的问题,以下便是其中一些:
注意:这些问题虽然在 Java 8 和 9 中得到了解决,但在 API 24 以下的 Android SDK 中是不可用的,这使得它们实际上无法使用。
对于 optionals 没有本地支持:虽然有 Optional 类,但它的使用意味着生成大量的样板代码,如果对选项的支持是在语言本身内构建的,而不是扩展的,我们可以保存这些代码。
对于函数式编程,没有本地的支持:在 Java 中,有 Stream API (再说一次,它只支持从 API 24 开始的 Android),但是它在语言中的集成类似于 Optional;它不存在于与原始类型相关联的对象中(IntStream,DoubleStream…),并且通过一个 Stream class 提供给所有其他对象。
支持匿名函数(Lambdas):尽管 Java 8 包含了对 Lambda 函数的支持,但这些都不是一级公民;这意味着,尽管我们可以使用 lambdas 以单个方法实现匿名接口,但 Java 不支持将函数作为参数传递给方法。另外,由于在语言中缺乏对它们的支持,类型推断的缺失使得 Lambdas 的语句非常不舒服,特别是在试图模拟函数比如函数组合或局部套用时。
Type nullability:虽然这可以包含在可选的部分中,但是这个问题的维度应该特别提到。有多少 Java 程序员试图通过 if (foo! = Null) 与可怕的 NullPointerException 斗争,而没有填满他们的代码?(事实上,它的创建者应该为他所说的“十亿美元的错误”道歉),而这些检查中有多少是为了避免在我们的应用程序中出现崩溃而做出的补丁呢?
Binding of manual views:尽管这个问题是针对 Android 平台的,而不是针对 Java 的,但它也需要样板代码,以获得对 Android 视图的引用。尽管我们已经通过 dataBinding 成功地消除了不受欢迎的 findViewById(int id),但我们仍然需要存储对该绑定的引用。
为什么 Kotlin 会打破这一切?
Java 是一种非常冗长的语言,它需要为任何操作编写大量的代码,并生成大量的文件(每个类一个)。第一个问题可能会导致我们代码的维护成本更高,更容易出现错误。第二个问题是 class proliferation 问题。
正是由于这些原因,今天,Java 被认为至少在 Android 开发中,并没有以行业的速度发展。随着时间的流逝,需要有一种现实和原生支持的语言来解决所有上面提到的问题变得越来越必要,这种语言需要同时拥有我在本文开头提到的主要特点:编写和编译一个应用程序,使它可以运行在任何设备和版本上。
在这个方向上,许多可能性已经被探索,其中一些是使用 Swift 或 Scala,尽管没有一个是非常有希望的。所有这些都随着 Kotlin 语言的出现而改变。Kotlin 是由 Jetbrains 设计和开发的一种语言,这种语言还在不断的进化中,最重要的是,它可以在 JVM 上执行。这使它成为 Android 应用的完美候选者。
为了证明这一点,我们可以列出在面对 Java 的所有缺点时,Kotlin 表现出的优势:
Optionals:他们被构建在 Kotlin;你所要做的就是声明一个变量的类型以问号结尾,这样它就变成了 optional 的类型。Kotlin 还提供了安全打开那些 optionals listener ?.onSuccess() 的可能性,而无需检查 optional 有没有值,并且还提供了 Elvis Operator。
函数式编程:在 Kotlin 中,我们找到了本地支持来处理像 Streams 这样的集合和数据集。我们可以在一个 collection 中直接调用 .flatMap {} 或者 .filter {}、.map {} 等等。类型的推断使得使用 Lambdas 变得特别容易。
Lambdas 和高阶函数:在 Kotlin 中,函数是一级公民的事实已经完成。我们可以定义接收其他函数作为参数的函数。一个例子是 map 函数本身的定义:
虽然乍一看,这段代码看起来有点混乱,我们感兴趣的部分是 transform:(T)- > R 。这意味着 map 函数有一个参数 transform,这本身就是一个函数,它有一个 T 类型的输入参数,并返回一个对象类型的 R。
由于本地对 lambdas 的支持,在 Kotlin 中,我们可以使用 map 函数:
inline fun <T, R> Iterable.map(transform: (T) -> R): List (source)
此代码片段将返回由 aTransformation 生成返回类型的元素集合。
collection.map { item -> aTransformation(item) }
Type nullability:在Kotlin中,由于有对optionals的集成支持,我们的代码中应该有最小可能的nullables。但即便如此,Kotlin还是提供了比Java更容易处理的工具。例如,我们有safe call (?) 来避免NullPointerException,或者在我们想要执行转换时使用操作符安全的cast来保护我们。另外,Kotlin的编译器强制控制可能具有空值的类型,甚至在与Java代码兼容的情况下引入运行时检查。
Binding of views:这是一个具体的 Android 问题,Jetbrains 为我们提供了 Kotlin Android 扩展;一个官方的支持库通过一个 gradle 的插件来简化这个问题(以及其他一些问题)。
Java:
public interface Listener {
void success(int result);
void error(Exception ex);
}public void someMethod(Listener listener) {
int rand = new Random().nextInt();
if(listener != null) {
if (rand <= 0) {
listener.onError(new ValueNotSupportedException());
}
else {
listener.success(rand);
}
}
public void fun(Type1 param1) {
param1.someMethod(new Listener() {
@Override
public void success(int result) {
println(“Success” + result);
}
@Override
public void error(Exception ex) {
ex.printStackTrace();
}
}
}
Kotlin:
fun someMethod(success: (Int) -> Unit, error: (Exception) -> Unit) {
val rand = Random().nextInt()
if (rand <= 0) {
error(ValueNotSupportedException())
else {
success(rand)
}
}
}fun (param1: Type1) {
param1.someMethod( {
println(“Success” + it);
}, {
it.printStackTrace();
})
}
或者使用表达式:
fun someMethod(success: (Int) -> Unit, error: (Exception) -> Unit) {
val rand = Random().nextInt()
if (rand <= 0) error(ValueNotSupportedException()) else success(rand)
}fun (param1: Type1) {
param1.someMethod( {
println(“Success” + it);
}, {
it.printStackTrace();
})
}
总结
现在,相信大家自己也应该很清楚,哪一个片段更容易编写和解释。基于以上,我们所讨论的,以及许多其它的功能,都在不断的证明,Kotlin 似乎是未来几年移动开发领域最有希望的赢家。
————— END —————