Kotlin VS Java:谁更适合 Android 开发?

2017 年,Google 宣布 Kotlin 成为 Android 的官方语言后,人们对于 Kotlin 的关注度就一直在上升。根据广大 Android 开发者反馈,Kotlin 帮助他们提高了生产效率和应用程序质量,对其有很高的满意度。并且数据显示 Google Play 商店中排名前 1000 的 Android 应用中有超过 80% 使用 Kotlin, Android 官方团队也都在用 Kotlin 写底层的源码。显然,对于 Android 开发者而言,Kotlin 已是一道无法绕过去的坎。

Kotlin vs Java:编程语言之战

在 Kotlin 出现之前,绝大部份 Android 开发者都是使用的 Java 语言,Java 有着许多明显的优点,如简单易学、面向对象、跨平台可移植性好等,在他们心中 Java 就是最好的编程语言。然而在 Kotlin 出现之后,这种对 Java 的信念有些动摇,程序员们开始搜索:

  • Kotlin 和 Java 哪种语言更好?
  • 对于 Android 开发,Kotlin 和 Java 哪个更好?

    本文就将尝试回答以上的两个疑问。

    什么是 Java?

    Java 是一种广泛使用的计算机编程语言,拥有 跨平台、面向对象、泛型编程的特性,广泛应用于企业级 Web 应用开发和移动应用开发。

    在 Android 系统中,系统 App 层和 Framework 层的几乎所有代码(目前已有部分改为 Kotlin)都由 Java 语言实现。

    Java 语言的优点:

    1. 跨平台可移植性好:得益于 Java 虚拟机的存在,实现一次编写,到处运行(Write once, run anywhere)
    2. 简单易学:Java 是面向对象的编程语言,容易理解,省去多重加载、指针等难以理解的概念。并且实现了垃圾自动回收机制,大大简化了程序设计
    3. 健壮:Java 的强类型机制、异常处理、垃圾的自动收集等是 Java 程序健壮性的重要保证
    4. 安全可靠:它的许多库都由 Google、Apache 等受信任的公司管理

    Java 语言的挑战:

    1. 运行速度较慢:Java 运行依赖于 Java 虚拟机,所以相对于其他语言(汇编、C/C++)编写的程序更慢,因为它不是直接执行机器码
    2. 缺少闭包(closure):闭包的缺失使得 Java 中函数式编程支持较差
    3. 测试驱动开发: 需要编写更多代码,并且会带来更高的编程错误风险
    4. 原生类型(Primitive types):原生类型的存在导致 Java 不是完美的面向对象语言,并且会造成一些编程问题。Java5 中通过自动装箱特性也没有完美解决

    什么是 Kotlin

    Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,由 JetBrains 设计开发并开源。

    Kotlin 语言的优点:

    1. 语言简洁:Kotlin 具备简洁的语法和现代化的语法特性,与 Java 相比,用 Kotlin 编写的代码块更小。
    2. 与 Java 兼容性好:Kotlin 将代码编译为可以在 JVM 中执行的字节码。因此,所有用 Java 制作的库和框架都在 Kotlin 项目中都通用
    3. 安全性好:空安全机制降低了 NullPointerException 发生的概率
    4. 结构化并发:Kotlin 协程使异步代码与阻塞代码一样易于使用

    Kotlin 语言的挑战:

    1. 不太受欢迎:与 Java 等其他成熟的语言相比,Kotlin 并不那么受欢迎。所以稳定的库、框架和教程更少
    2. 匹配弱模式:初始代码可读性变差
    3. 学习曲线陡峭:入门容易,精通困难

    Kotlin 与 Java 比较

    尽管 Kotlin 是官方支持的用于编写 Android 应用的语言,但您仍然可能觉得没有足够的理由进行切换。而以下对比,比较详细地囊括了 Kotlin 相比于 Java 的优点。

    特征JavaKotlin
    检查异常
    代码简洁不是很简洁比 Java 好
    协程
    数据类需要编写大量样板代码只需要在类定义中添加 data 关键字
    扩展函数
    高阶函数和 Lambda高阶函数是使用 Callables 实现的。Java 8 中引入了 Lambda 表达式预建功能
    内联函数
    对委派的原生支持
    非私有领域
    空指针异常
    基本数据类型基本类型的变量不是对象基本类型的变量是对象
    智能转换
    静态成员
    三元运算符
    通配符类型

    使用语法对比

    1. 空指针安全

    NullPointerException 或 NPE 是 Java 的主要缺点之一,NPE 的唯一可能原因是显式调用抛出 NullPointerException。一些与初始化相关的数据不一致,或由外部 Java 代码引起的其他问题。 而 Kotlin 避免了 NullPointerException。每当可能抛出 NullPointerException 时,Kotlin 都会在编译时失败。

    2. 数据类

    使用 Java 编写数据类,通常开发者需要定义一个构造函数、几个存储数据的字段、每个字段的 getter 和 setter 函数,以及 equals()、hashCode() 和 toString() 函数。

    class Book { private String title;
      private Author author;
      public String getTitle() { return title;
      }
      public void setTitle(String title) { this.title = title;
      }
      public Author getAuthor() { return author;
      }
      public void setAuthor(Author author) { this.author = author;
      }
    }
    

    Kotlin 有一种非常简单的方法来创建这样的类。开发者只需要在类定义中包含 data 关键字,编译器将自行处理整个任务。

    data class Book(var title: String, var author: Author)
    

    3. 扩展函数

    Kotlin 允许我们在不继承现有类的情况下扩展现有类的功能。意思是说,Kotlin 提供了开发具有新功能的类的能力,而无需从类继承,扩展函数可以做到这一点。 声明一个扩展函数,需要在它的名字前面加上一个接收器类型,即被扩展的类型。下面为 MutableList 添加了一个用于指定下标进行数值交换的函数:

    fun MutableList  .swap(index1: Int, index2: Int) { val tmp = this[index1] 
      this[index1] = this[index2] 
      this[index2] = tmp 
    }
    

    扩展函数中的“this”关键字对应于接收者对象,在“.”之前传递。现在可以在任何 MutableList 上调用这个函数:

    val list = mutableListOf(1, 2, 3) 
    list.swap(0, 2)
    

    4. 智能转换

    Kotlin 的编译器能够自动进行类型转换。在许多情况下,不需要在 Kotlin 中使用显式转换运算符,但 Kotlin 对不可变值有“is-checks”,并在需要时自动插入转换

    fun demo(x: Any) { if (x is String) { print(x.length) // x 自动转换为字符串
      } 
    }
    

    5. 类型推断

    在 Kotlin 中,不必显式指定每个变量的类型。

    fun main(args: Array < String > ) { val text = 10 //无需显示变量类型,Kotlin 自动识别为 Int 类型
      println(text) 
    } 

    6. 函数式编程

    Kotlin 与 Java 对比中一个重要的区别在于 Kotlin 是一种函数式编程语言。Kotlin 由许多有用的方法组成,其中包括高阶函数、lambda 表达式、运算符重载、惰性求值等等。 函数式编程让 Kotlin 在集合方面更加方便:

    fun main(args: Array < String > ) { val numbers = arrayListOf(15, -5, 11, -39) 
      val nonNegativeNumbers = numbers.filter { it >= 0 
      } 
      println(nonNegativeNumbers) 
    }
    

    高阶函数就是一个函数的参数是函数,或者返回值是函数,满足其中一个就是高阶函数。

    考虑以下代码:

    fun alphaNum(func: () -> Unit) {}
    

    在上面的代码中,“func”是参数的名称,“() -> Unit”是函数类型。在这种情况下,func 是一个不接收任何参数且也不返回任何值的函数。

    Lambda 表达式的本质其实是匿名函数,因为在其底层实现中还是通过匿名函数来实现的。Lambda 作为函数式编程的基础,其语法也是相当简单的。 一个 Lambda 表达式的例子:

    val sum: (Int, Int) -  > Int = { x, 
      y - > x + y 
    }
    

    在上面的例子中,我们简单地声明了一个变量“sum”,它接受两个整数并将它们相加,然后以整数形式返回总和,然后我们只需使用“ sum(2, 2) ”来调用它。

    总结

    通过以上多方面对比可以看到,对于 Android 开发,Kotlin 显然更优于 Java。 之所以如此,是因为 Kotlin 与 Java 良好的互通性,从 Java 迁移到 Kotlin 的成本很低,并且 Kotlin 在 Java 基础上有了许多更优的改进。可以说 Kotlin 其实是站在了 Java 这个巨人的肩膀上,Kotlin 的出现,就是为了改良 Java 而生的。大胆预测,在不久的将来 Kotlin 会成为企业应用程序和移动设备的 First Language。

    参考文献

    Kotlin vs Java: Which is Better for Android App Development?