从Java到Koltin的基础教程(一):基础语法
Kotlin 是什么?
A modern programming language that makes developers happier.
一种使开发人员更快乐的现代编程语言。
Kotlin 是由 JetBrains 设计的 JVM 平台语言,并支持与 Java 完全互操作。JetBrains 自家的 IntelliJ IDEA 对 Kotlin 具有一流的支持,智能 + 简洁 + 互操作,高版本一键迁移等极佳的开发体验。
简短的时间线为:
- 2011.07 JetBrains 推出 Koltin,一款基于 JVM 的新语言,并选择以圣彼得堡附近的 Koltin Island 命名。
- 2016.02 JetBrains 发布 Koltin 1.1 版,提供 JVM 和 JavaScript 两种编译目标,并承诺长期向后兼容。
- 2017.05 Google 宣布在 Android 上对 Kotlin 提供一流的支持。
- 2017.11 Kotlin 1.2 发布,提供实验性多平台项目功能。
- 2018.10 Koltin 1.3 发布,协程正式发布。
- 2019.05 Google 宣布 Kotlin 是 Android 开发者的首选语言。
- 2020.08 Kotlin 1.4 发布,进行大量底层优化,提供新的编译器后端等功能。
- 2021.05 Koltin 1.5 发布,支持 JVM Records、密封类改进、新增内联类等功能。
- 2021.11 Kotlin 1.6 发布,包含编译器优化、类型推断优化、类型参数注解等功能。
为什么选择 Koltin ?
可能有同学会问,从上述事件表看,Kotlin 对 Android 开发很有用,并且 Google 已经指定为首选语言,但它对于后端而言有什么意义呢,为什么我要学它呢?
这里列举几个官方给出的优点:
- 代码简洁,与 Java 相比能通过更少的代码,更高效的完成编程。
- 空安全,基于类型系统的空检查,让 NullPointException 无处可逃。
- 互操作,完全支持 Java 生态,无缝继承来自于 Java 所有库。
- 多平台,支持 桌面、IOS、Android、Web 开发。
- Native, 允许编译为机器原生字节码,获得更高的效率、更低的资源占用。
另外,Kotlin 不仅在 Android 端有大量的优化支持,早在2017年,[Spring 官方](Introducing Kotlin support in Spring Framework 5.0)已经对 Kotlin 提供了出色的支持(当然也得益于 Koltin 对 Java 完全互操作),我们来体验一段:
// BlogApplication.kt
@SpringBootApplication
class BlogApplication
fun main(args: Array<String>) {
runApplication<BlogApplication>(*args) {
// 设置banner
setBannerMode(Banner.Mode.OFF)
// 定义Bean
beans {
bean<Foo>()
bean<Bar>("bar")
profile("baz") {
profile("pp") {
bean<Foo>()
}
bean { Baz(it.ref<Bar>()) }
bean { Baz(it.ref("bar")) }
}
}
}
}
// IntegrationTests.kt
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class IntegrationTests(@Autowired val restTemplate: TestRestTemplate) {
@Test
fun `Assert blog page title, content and status code`() {
val entity = restTemplate.getForEntity<String>("/")
assertThat(entity.statusCode).isEqualTo(HttpStatus.OK)
assertThat(entity.body).contains("<h1>Blog</h1>")
}
}
如果看完这段代码,你对 Kotlin 产生了小小的兴趣的话,那么让我们一起继续探索吧!
第一次开始:main 函数
无参 main:
有参 main:
与之相对应的 Java:
public class HelloWorld{
public static void main(String[] args){
System.out.println("Hello Java!");
String argsJoin = Arrays.stream(args).collect(Collectors.joining(",", "[", "]"));
System.out.println(argsJoin);
}
}
经过对比,我们可以发现一个特点,Koltin 中的 main 函数既不需要在一个类文件(Class)中,也不需要静态(static)修饰符。原因是是由于 Koltin 支持顶层函数^1^以及 main 方法的特殊地位^2^。
1 顶层函数、顶级属性:Koltin 认为,对于一些工具类中的方法、属性等,只是受限于 Java 必须有类定义,但实际上并不需要这些繁冗的容器类,所以 Koltin 允许在文件中直接声明函数、属性,称为顶级(层)函数,顶级属性。
2 main 方法的特殊地位:在 Koltin 中 main 函数只是看起来简洁了些,实际上编译后的结果,依然是
public static void main(String[] args)
。至于Koltin 中的无参 main 方法,是一个语法糖,用于省略不需要接收外部参数的场景。
变量
Koltin 中定义变量有两种方式 val 和 var,分别对应着 不可重新赋值 和 可重新赋值。val 声明的变量必须初始化,否则无法编译,var 则可以在声明变量之后再进行赋值,但必须先声明 var 变量的类型。
与之等效的Java:
final Integer a = 1;
final Integer b = 1;
// final Integer c;
Integer c = 1;
c = 114;
Integer d;
d = 514;
注意,此 Java 代码仅仅是等效,并非实际的 Koltin 编译结果,仅仅演示对比。Kotlin 在编译时检查 val、var 定义的变量,但不会生成上述代码中包含的 final 关键字。
空检查
可空类型
Kotlin 中类型分为非空、可空两种,以‘?’声明。
与之对应的Java:
int a = 129;
Integer b = null;
b = (Integer)null;
Integer c = 129;
在 Koltin 中,基本类型的可空对象将会自动使用包装类型(Integer、Double..)
Elvis 运算符?:
Kotlin 中不存在三元运算符,唯一近似的 a?:b
含义为:当 a 为空时取 b 。
与之等效的Java:
Integer a = 1;
Integer b = null;
System.out.println(b == null ? b : a);
Integer c = b == null ? b : a;
if (b == null){
return;
}
if (b == null){
throw new RuntimeException("'b' must not be null")
}
null条件检查
当可空类型遇上 if 判断是否为空...
安全调用
当需要安全调用可空类型时,可以使用?
来调用实例方法,对象为空时,静默取消后续调用,当对象非空时,继续调用
非空断言 !!
当明确的知道某个可空类型,一定不为空时,可以使用 !! 来强制进行调用,但务必注意,它会抛出空指针异常。并且代码段上文中出现 !! 后,那么该可空类型的后续所有操作都允许直接调用。
个人不太推荐使用,在开发过程中,往往有些看上去不可能为空的对象,实际运行时给你不可思议的惊喜。
类型转换
Koltin 中类型转换的关键字为 as
,并且支持通过?
进行安全转换
比较
Kotlin中,a == b
相当于 Java 的a.equals(b)
,a === b
相当于 Java 的 a == b
。
基本类型的比较有些许不同,将在下节介绍。
结束语
至此,Kotlin的简单历史和基础语法就到此结束了~