Kotlin
- 自诞生之日开始就有强大的 IDE 支持的编程语言
Kotlin
是著名的 Java
开发工具 IntelliJ IDEA
母公司 JetBrain
开发的现代编程语言,其运行在 JVM
之上,号称与 Java
百分之百互操作性。
100% interoperable with Java™ and Android™
由于 JetBrain
本身就是做 IDE
出名,因此 Kotlin
语言可以说从诞生之日开始就有着强大的 IDE
支持了。为什么 JetBrain
选择创建一门新的编程语言而不是在 IDE
工具中提供更强大便捷的功能,或者对 Java
语言进行改进呢?那些觉得 Kotlin
仅仅是提供了一堆语法糖,除此之外别无其它了的人可能更有此疑问。
Java
从 1996 年发布第一个开发工具 JDK1.0
开始,经历二十几年的发展,Java 8
已经发布稳定版,Java 9
也提上了日程。但 Java
发展史上谈得上有重大更新的语言特性无非是 Java 5
范型和 Java 8
的 lambda
表达式。Java 5
的范型相对于与其对标的 C++ Template
和 C#
的范型功能上略显鸡肋;Java 8
的 lambda
表达式相比于其它众多现代编程语言的 函数式编程 也显得”小巫见大巫”。相信 JCP
也并非不想大刀阔斧的对 Java
进行改进以赶上潮流,但由于 Java
本身的语言特性以及新版本的 Java
要保证旧版本 向后兼容,对 Java
进行重大改进可能性极低,在开发工具上下手性价比过低。
为什么选择 Kotlin
1. 简洁
极大地减少大量的模板代码
Java
开发者熟悉的 Java Bean
是典型的模板代码,典型的 Java Bean
包含
* 一系列的私有字段
* 包含以上所有字段的构造函数、无参构造函数
* 以上私有字段对应的 getter/setter
方法
* 重写从 Object
继承下来的 hashCode
和 equals
方法
一个 Java
编写的 Bean Person
import java.io.Serializable;
import java.util.Objects;
public class Person implements Serializable {
private Integer id;
private String name;
private Integer age;
public Person(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public Person(String name, Integer age) {
this(null, name, age);
}
public Person() {
}
public Integer getId() {
return id;
}
private void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(id, person.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
使用 Kotlin
改写的版本
data class Person(var id: Int? = null, var name: String? = null, var age: Int? = null)
是的,你没有看错,只有一行代码。如果你还在怀疑这一行 Kotlin
代码是否能给到 46 行 Java
代码所能给的效果,那么请看它们最终 .class
文件反汇编出来的:
Java
版 (只显示声明,未显示实现)
public class Person {
public Person(java.lang.Integer, java.lang.String, java.lang.Integer);
public Person(java.lang.String, java.lang.Integer);
public Person();
public java.lang.Integer getId();
public void setId(java.lang.Integer);
public java.lang.String getName();
public void setName(java.lang.String);
public java.lang.Integer getAge();
public void setAge(java.lang.Integer);
public boolean equals(java.lang.Object);
public int hashCode();
}
Kotlin
版 (同上, 方法顺序有调整)
public final class Person {
public Person(java.lang.Integer, java.lang.String, java.lang.Integer);
public Person(java.lang.Integer, java.lang.String, java.lang.Integer, int, kotlin.jvm.internal.DefaultConstructorMarker);
public Person();
public final java.lang.Integer getId();
public final void setId(java.lang.Integer);
public final java.lang.String getName();
public final void setName(java.lang.String);
public final java.lang.Integer getAge();
public final void setAge(java.lang.Integer);
public boolean equals(java.lang.Object);
public int hashCode();
public final java.lang.Integer component1();
public final java.lang.String component2();
public final java.lang.Integer component3();
public final Person copy(java.lang.Integer, java.lang.String, java.lang.Integer);
public static Person copy$default(Person, java.lang.Integer, java.lang.String, java.lang.Integer, int, java.lang.Object);
public java.lang.String toString();
}
更少的 Kotlin
代码比更多的 Java
代码给的更多(但不是无用的)。
2. 安全
Kotlin
相比于 Java
一大特性就是 null safe
:
- 一个变量,除非显式说明其为
Optional
(允许为null
) ,否则它就是非空的; - 在允许为空的变量上所作的任何假设其非空的操作都会在编译时被检测出来。众所周知,编译时异常比运行时异常代价可要便宜很多。
// 1
var person: Person
// ... 很多其他代码
person = null // 编译时错误
// 2
var person: Person? = null // 允许为空的类型
// ... 很多其他代码
person.toString() // 编译时错误
另一种安全是类型安全转换:
在判断类型时,如果类型判断正确,kotlin
将自动为你转换好:
var person: Person
// ... 很多其他代码
if (person is Manager) {
// 此处 person 已经为 Manager 类型的了
} else if (person is Emploee) {
// 此处 person 已经为 Emploee 类型的了
}
3. 与已有 Java
代码可互操作
如果为了获得 Kotlin
的新特性而要放弃现有的丰富的 Java
库,并且重写现有的 Java
项目代码,那性价比可以说是非常低了。由于 Kotlin
与 Java
一样都是基于 JVM
,它们的共同目标代码就是 JVM
的字节码,因此在互操作性上不会有很大的障碍。从拥有二十几年发展历史的 Java
转移到新生的 Kotlin
, 我更关注 Kotlin
调用 Java
现有库的能力。反之也不会太令人失望。
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
@RestController
@RequestMapping("/api/v1/users/")
class UserRestController : LogAware {
@Autowired
private lateinit var userService: UserService
@GetMapping
fun getUsers(@RequestParam(defaultValue = "all") userType: String,
@RequestParam(defaultValue = "all") type: String,
@RequestParam(defaultValue = "0") from: Int,
@RequestParam(defaultValue = "100") limit: Int): ResponseEntity<*> {
return ResponseEntity.ok(userService.getUsers(userType, type, from, limit))
}
@PutMapping
fun updateUser(@RequestBody user: User): ResponseEntity<*> {
return ResponseEntity.ok().body(userService.updateUser(user))
}
}
无论是 JDK
自带的还是第三方的库、普通类型、注解,都可以直接使用,不用重新造轮子了。
4. 开发工具友好
优秀的编程语言需要优秀的开发工具,没有开发工具的支持,优秀的语言特性带来的效益将被繁琐的环境搭建和构建过程所抵消(甚至超过)。Kotlin
母公司自家的 IDE
IntelliJ
不仅在基本的语法补全方面提供支持,在代码重构,代码分析等方面也有出色的表现。如果你还是 Eclipse
的忠实守护者,Kotlin
也有 Eclipse
的开发插件。对于不喜欢 IDE
生成一堆无关文件,喜欢自己掌控所有细节的人,可以使用 Kotlin
的编译器 在命令行下手动编译代码。