JetBrains有一个明确的目标:让Kotlin成为一种多平台语言,并提供100%的Java互操作性。Kotlin最近的成功和成熟水平为它进入服务器端提供了一个很好的机会。
选择Kotlin的理由
许多语言都试图成为更好的Java。Kotlin在语言和生态系统方面做得都很好。成为更好的Java,同时又要保护JVM和巨大的库空间,这是一场姗姗来迟的进化。这种方法与来自JetBrains和谷歌的支持相结合,使它成为一个真正的竞争者。让我们来看看Kotlin带来的一些特性。
类型推断 —— 类型推断是一等特性。Kotlin推断变量的类型,而不需要显式指定。在需要明确类型的情况下,也可以指定类型。
通过引入var关键字,Java 10也在朝着类似的方向发展。虽然表面看起来类似,但它的范围仅限于局部变量,不能用于字段和方法签名。
严格空检查 —— Kotlin将可空代码流视为编译时错误。它提供了额外的语法来处理空检查。值得注意的是,它提供了链式调用中的NPE保护。
与Java互操作 —— Kotlin在这方面明显优于其他JVM语言。它可以与Java无缝地交互。可以在Kotlin中导入框架中的Java类并使用,反之亦然。值得注意的是,Kotlin集合可以与Java集合互操作。
不变性 —— Kotlin鼓励使用不可变的数据结构。常用的数据结构(Set/ List/ Map)是不可变的,除非显式地声明为可变的。变量也被指定为不可变(val)和可变(var)。所有这些变化对状态可管理性的影响是显而易见的。
简洁而富有表达力的语法 —— Kotlin引入了许多改进,这些改进对代码的可读性产生了重大影响。举几个例子:
在Kotlin中,所有的函数都是表达式,因为它们至少返回Unit 。控制流语句如if、try和when(类似于switch)也是表达式。例如:
循环支持范围,例如:
还有一些其他的改进,我们将继续讨论。
考虑到Java的互操作性,建议循序渐进地将Kotlin添加到现有的Java项目中。主流产品的支持项目通常是不错的选择。一旦团队感到舒适了,他们就可以评估自己是否更喜欢完全切换。
选择哪类项目好?
所有的Java项目都可以从Kotlin中获益。但是,具有以下特征的项目可以使决策更简单。
包含大量DTO或模型/实体对象的项目 —— 这对于处理CRUD或数据转换的项目非常典型。此类项目往往充斥着getter/setter。这里可以利用Kotlin的属性大幅简化类。
大量依赖实用工具类的项目 —— Java中的实用工具类通常是为了弥补Java中顶级函数的缺乏。在许多情况下,这包括含全局无状态public static函数。这些可以分解成纯函数。更进一步,Kotlin支持类似Function类型这样的FP结构和高阶函数,这可以用来使代码更易于维护和测试。
类中逻辑复杂的项目 —— 这些项目容易受到空指针异常(NPE)的影响,而这是Kotlin很好地解决了的其中一个问题。通过让语言分析可能导致NPE的代码路径为开发人员提供支持。Kotlin的when结构(一个更好的switch)在这里非常有用,可以将嵌套的逻辑树分解为可管理的函数。对变量和集合的不变性支持有助于简化逻辑,避免由于引用泄漏而导致难以查找的错误。虽然上面的一些功能可以通过Java实现,但Kotlin的优势在于升级了这些范例,并使它们保持简洁一致。
让我们在这里暂停一下,看一个典型的Java逻辑片段以及对应的Kotlin实现:
对应的Kotlin实现:
虽然这些代码片段在功能上是等效的,但是它们有一些明显的区别。
logic()函数不需要包含在类中。Kotlin提供了顶级函数。这开辟了一个广阔的空间,鼓励我们去思考是否真的需要一个对象。单独的纯函数更容易测试。这为团队提供了采用更简洁的函数方法的选项。
Kotlin引入了when,这是一个处理条件流的强大结构。它比if或switch语句的功能要强大得多。任意逻辑都可以使用when进行条理的组织。
注意,在Kotlin版本中,我们从未声明返回变量。这是可能的,因为Kotlin允许我们使用when和try作为表达式。
在subLogicA函数中,我们可以在函数声明中为paramB指定一个默认值。
private fun subLogicA(paramA: String, paramB: String = "DEFAULT"): String {
现在,我们可调用任何一个函数签名了:
subLogicA(paramA, paramB)
或者
subLogicA(paramA)
# In this case the paramB used the default value in the function declaration
现在,逻辑更容易理解了,代码行数减少了约35%。
Maven和Gradle通过插件支持Kotlin。Kotlin代码被编译成Java类并包含在构建过程中。Kobalt等比较新的构建工具看起来也很有前景。Kobalt受Maven/Gradle启发,但完全是用Kotlin编写的。
首先,将Kotlin插件依赖项添加到Maven或Gradle构建文件中。
如果你使用的是Spring和JPA,你还应该添加kotlin-spring和kotlin-jpa编译器插件。项目的编译和构建没有任何明显的差异。
如果要为Kotlin代码库生成JavaDoc则需要这个插件。
有针对IntelliJ和Eclipse Studio的IDE插件,但正如我们所预料的那样,Kotlin的开发和构建工具从IntelliJ关联中获益良多。从社区版开始,该IDE对Kotlin提供了一等支持。其中一个值得注意的特性是,它支持将现有的Java代码自动转换为Kotlin。这种转换很准确,而且是一种很好的学习Kotlin惯用法的工具。
因为我们将Kotlin引入了现有的项目中,所以框架兼容性是一个问题。Kotlin完美融入了Java生态系统,因为它可以编译成Java字节码。一些流行的框架已经宣布支持Kotlin,包括Spring、Vert.x、Spark等。让我们看下Kotlin和Spring及Hibernate一起使用是什么样子。
Spring
Spring是Kotlin的早期支持者之一,在2016年首次增加支持。Spring 5利用Kotlin提供更简洁的DSL。你可以认为,现有的Java Spring代码无需任何更改就可继续运行。
Kotlin中的Spring注解
Spring注释和AOP都是开箱即用的。你可以像注解Java一样注解Kotlin类。考虑下面的服务声明片段。
这些是标准的Spring注解:
@Service: org.springframework.stereotype.Service
@CacheConfig: org.springframework.cache
注意,constructor是类声明的一部分。
@Autowired constructor(private val tokenRepo: TokenRepository)
Kotlin将其作为主构造函数,它可以是类声明的一部分。在这个实例中,tokenRepo是一个内联声明的属性。
编译时常量可以在注解中使用,