1.2 语言特性

人们为什么喜欢Kotlin? Kotlin为什么值得我们去学习?下面是一个不完全的清单列表。

  •  与Java及JVM的完全互操作性;
  •  多平台:适合Android、浏览器(JavaScript)和本地系统编程(native);
  •  语法简洁不啰嗦(便于学习);
  •  富于表现力和高效的生产力;
  •  支持类型推断。例如,我们可以只写val number=23,编译器会推断这是一个Int;
  •  可以使用数据类(data class)以极简的方式创建POJO;
  •  运算符重载相当简单;
  •  快速、方便地扩展内置类、自定义类的函数与属性;
  •  区分可空类型和不可空类型。直接在编译期语法层面检查可空类型,提供空安全保障;
  •  Kotlin含有功能丰富的集合类Stream API;
  •  集成扩展了简单实用的文件I/O、正则匹配、线程等工具类;
  •  提供了实用强大的函数式编程支持:一等函数支持,Lambda表达式、高阶函数等;
  •  能够轻松、方便地创建DSL;
  •  使用更加轻量级的协程进行并发编程;
  •  IntelliJIDEA开发工具的一等支持;
  •  Android开发有Android Studio 3内置原生支持;
  •  提供的Anko库(https://github.com/Kotlin/anko)使得Android开发速度更快,充满更多的乐趣等。

Kotlin的优势是既有Java的完整生态(Kotlin完全无缝使用各类Java API框架库),又有现代语言的高级特性(语法糖)。

Kotlin语言的设计初衷之一是为了JetBrains团队内部使用,旨在帮助公司降低成本。用过IntelliJ IDEA的程序员都知道JetBrains团队的出品皆是良品。毫无疑问,Kotlin的设计是务实的。发展和促进Kotlin的好处大于其成本,在这个过程中,Kotlin已经演变成了一个JetBrains的效率工具,其显著的务实特性吸引了一大批Java程序员,并成为了JetBrains工具生态系统中重要的一员。

在未来几年内,Kotlin有望成为主要的非Java的JVM语言,甚至有一天成为下一个“Java”语言。可以预测的是,Kotlin将大大提升整个Java互联网开发者的效率和质量。

Kotlin语言的特性可以简单概括为以下几方面。

1. 实用主义(Pragmatic)

务实、注重工程实践性。我们经常会听到人们说编程是数学,或者是工程,是艺术,是科学,这些说法都是很有道理的。Kotlin是一门偏重工程实践、编程上有极简风格的语言。

2. 极简主义(Minimalist)

Kotlin语法简洁优雅不啰嗦,类型系统中一切皆是引用(reference)。

3. 空安全(Null Safety)

Kotlin中有一个简单完备的类型系统来支持空安全。

4. 多范式(multi-paradigm)

Kotlin同时支持OOP与FP编程范式。各种编程风格的组合可以让我们更加直接地表达算法思想和解决问题的方案,可以赋予我们在思考上有更大的自由度和灵活性。

5. 可扩展

Kotlin可直接扩展类的函数与属性(extension functions & properties)。这与我们在Java中经常写的util类是完全不一样的体验!Kotlin是一种非常注重用户体验的语言。

6. 高阶函数与闭包(higher-order functions & closures)

Kotlin的类型中,函数类型(function type)也是一等类型(first class type)。在Kotlin中可以把函数当成值进行传递,这直接赋予了Kotlin函数式编程的特性,使用Kotlin可以写出一些非常“优雅”的代码。

7. 支持快速实现DSL

有了扩展函数、闭包等特性的支持,使用Kotlin实现一个DSL将会相当简单、方便。

1.2.1 Kotlin与Java完全互操作

Kotlin是基于JVM平台的静态编程语言,同时在设计之初就把与Java的互操作性当作重要目标。正如官方网站所宣传的那样:100% interoperable with Java and Android。下面我们举个简单例子来展示Kotlin中使用Java的ArrayList类与使用JUnit测试框架进行单元测试。代码示例如下:

    fun getArrayList(): List<String> {             //(1)函数声明
        val arrayList = ArrayList<String>() //(2)Kotlin中直接调用Java的API
        arrayList.add("A")
        arrayList.add("B")
        arrayList.add("C")
        return arrayList
    }

代码说明如下。

(1):声明了一个返回List<String>的函数,我们看到在Kotlin中使用fun关键字来声明函数。

(2):创建了一个ArrayList<String>对象,我们可以看到,在Kotlin中创建对象不再使用new关键字了,尖括号里面的String是泛型信息。该语法与Java语言基本类似。关于集合类与泛型的相关内容,将在第7章和第8章中具体介绍。

下面使用JUnit框架进行单元测试。代码如下:

代码说明如下。

(3):是包声明,使用package关键字。

(4):使用import导入JUnit4类。

(5):Kotlin中使用@RunWith注解,方式与Java语法类似。注解中的参数是JUnit4::class,是JUnit4类的引用。我们将在第12章中介绍注解与反射。

(6):使用JUnit的@Test注解来标注这是一个测试方法。

(7):调用被测试函数getArrayList()。

(8):使用JUnit的Assert类的API进行断言操作。

1.2.2 扩展函数与扩展属性

扩展函数与扩展属性的“好玩”之处在于,可以在不修改原来类的条件下自定义函数和属性,使它们表现得就像是属于这个类一样。例如,我们给String类型扩展一个返回字符串首字母的firstChar()函数,代码如下:

然后就可以在代码中直接这样调用该函数:

代码显得相当简洁。

1.2.3 不可空类型与空安全

使用Kotlin编程比Java更加安全,至少在空指针问题上写起代码来会更加“开心”。Kotlin中引入了不可空类型与可空类型来明确声明一个变量是否可能为null,同时在编译期通过类型是否匹配来检查空指针异常,大大降低了空指针异常出现的概率。同时,Kotlin还提供了Elvis操作符、安全调用符等极简的语法格式,使开发者从Java的null防御式编程中被解放出来。例如下面的这段代码:

当声明了不可空类型String的变量a后,在后面使用变量a的代码中就不能给a赋值为null。如果给a赋值null,编译器会直接报错。而这个时候,如果我们想声明一个可空的String类型,可以这样写:

但是这个时候,如果想调用变量b的方法,就不能直接像下面这样写了:

我们可以看到,上面的代码运行报错:

    可空类型String? 只有使用安全调用符(?.)和非空断言调用符(?)才允许调用其方法。

如果在IDE中会直接提示报错,编译不通过。上面的代码可以使用安全调用符进行如下改写:

这个问号确实非常简洁易懂,同时能够时刻提醒我们:这个调用者有可能是null的。这个语法明显比Java 8中引入的Optional<String>更加简单、直接。

1.2.4 一等函数支持

在Kotlin中函数是第一等类型(fist class):我们可以将函数像值一样传递,函数可以作为另一个函数的返回值。我们通常称之为“一等函数(first order functions)”支持。例如,下面是一个把函数作为参数传递给函数的Lambda表达式的例子:

其中,{it%3!=0}是一个Lambda表达式,它判断元素是否能够被3整除。如果满足此条件就留下该元素,否则过滤掉。关于函数式编程的内容将在第5章中介绍。

1.2.5 智能类型推断

在上面的诸多例子中,可以看到在声明变量的时候并没有显式指定它的类型。Kotlin编译器会自动推断出其类型。

上面介绍的只是Kotlin诸多优秀特性中的一部分,更多内容且看后面的章节讲解。