跳到主要内容

Kotlin简介

欢迎来到 Kotlin 的神秘世界,Kotlin? 嗯,没错就是它! 也许你仅仅是听过它还没开始尝试; 也许你尝试过它但是放弃了; 也许你正在使用它遇到了一些些问题,也许你很喜欢它并且把它使用得如火纯青了。不管你现在是处于哪个阶段,我都希望你能从本教程中得到一些有用的东西。

本教程不打算按照书本上那样平铺直序阐述,而是带着问题和目的性展开,每个语法点主要都围绕着为什么使用它、它是什么、它是如何使用的、它的应用场景此外最后还会带你了解它语法糖背后的原理。因为 Kotlin 是一个门非常讲究实用主义的编程语言,所以一定是要用于解决实际的场景问题,或者相比现有的语言(比如 Java)它如何更高效解决实际问题。每节教程都会留有一个对应的语法练习,下一节会公布上一节的答案。

最后,欢迎一起努力来到 Kotlin 世界探险,一起领悟这门语言背后的设计哲学和实用价值。

1. Kotlin 是什么?

Kotlin 是一门用于现代多平台应用的静态编程语言,其中被广泛用于 Android 平台的开发,被称之为Android 世界的 Swift。它由大名鼎鼎的 JetBrains 公司设计开发并开源,著名的 IDE 工具 IntelliJ IDEA 就是他们的产品,所以无疑他们是对编程语言设计领域最为熟悉的专家。

Kotlin 从 2016 年发布 1.0 的 release 版本开始至今,使用的开发者数量快速增长。

图片描述

此外 Kotlin 已经拥有强大的生态和社区开发者的支持:

  • Kotlin 是著名的 IDE 厂商 JetBrains 公司开发的编程语言
  • 在 Google I/O 2017中,Google 宣布在 Android 上为 Kotlin 提供最佳支持
  • Kotlin 在 Spring5.0 后端开发框架中的支持
  • Kotlin DSL 1.0 将在 Gradle5.0 得以应用,Kotlin 成为继 Groovy 语言开发 Gradle 另一门编程语言
  • Kotlin 成为 2018 年 Github 中增长速度最快的语言
  • 2018年10月,Google 和 JetBrains 在 KotlinConf18 上公开宣布了 Kotlin 基金会
  • 2019年5月,谷歌宣布 Kotlin 作为 Android 的首选语言。
  • 2019年7月,Kotlin 在 O’Reilly 开源软件大会(OSCON)2019上赢得了享有声望的年度突破项目奖

2. 为什么选择 Kotlin?

2.1 简洁

可以大大减少样板代码。

  • 例如实现一个简单的Student 的 POJO 类:
//在Java实现一个Student POJO类,需要写setter,getter模板代码
class Student {
private String name;
private int age;
private String address;
private String phoneNumber;

public Student(String name, int age, String address, String phoneNumber) {
this.name = name;
this.age = age;
this.address = address;
this.phoneNumber = phoneNumber;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

public String getPhoneNumber() {
return phoneNumber;
}

public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}

//Kotlin实现一个Student POJO类,仅仅需要1行代码,就能创建一个包含setter,getter,equals,toString等POJO类
data class(val name: String, val age: Int, val address: String, val phoneNumber: String)

  • 例如实现一个简单的单例模式:
//Java实现一个单例模式
public class Singleton implements Serializable {
private Singleton() {
}

private static final Singleton mInstance = new Singleton();

public static Singleton getInstance() {//提供公有获取单例对象的函数
return mInstance;
}

public final void doSomething() {
System.out.println("do some thing");
}
}

//Kotlin实现上面Java一样的一个单例模式,仅仅只需要创建object即可
object Singleton : Serializable {//object对象表达式天生的单例模式
fun doSomething() {
println("do some thing")
}
}

  • 例如Kotlin中的 kotlin-android-extension助力 Android 开发,从此告别findViewById()模板代码:
//Java实现
public class MainActivity extends Activity {
private TextView mTvName;
private TextView mTvAddress;
private TextView mTvDes;
private ImageView mIvCover;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTvName = (TextView) findViewById(R.id.tv_name);
mTvAddress = (TextView) findViewById(R.id.tv_address);
mTvDes = (TextView) findViewById(R.id.tv_des);
mIvCover = (ImageView) findViewById(R.id.iv_cover);

mTvName.setText("Kotlin");
mTvAddress.setText("圣彼得堡附近的科特林岛");
mTvDes.setText("Kotlin 是一门用于现代多平台应用的静态编程语言");
mIvCover.setImageDrawable(R.drawable.icon_kotlin_cover);
}
}

//kotlin利用kotlin-android-extension实现
class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

//无需findViewById直接使用
tv_name.setText("Kotlin")
tv_address.setText("圣彼得堡附近的科特林岛")
tv_des.setText("Kotlin 是一门用于现代多平台应用的静态编程语言")
iv_cover.setImageDrawable(R.drawable.icon_kotlin_cover)
}
}

2.2 安全

可以能够很好地避免空指针(NPE)异常的出现。

大家都知道NPE异常是运行时异常,编译期很难发现NPE异常,Kotlin之所以能够很好避免NPE,主要关键在于它对类型系统做了非空和可空类型的划分,并且能在编译期将可能出现NPE的问题提前暴露出来。

  • 声明处赋值处进行 NPE 保护:
//声明处赋值处进行NPE保护
var name: String //定义一个非空String类型
name = null//当非空类型遇到null赋值,则会出现编译错误

var age: Int?//定义一个可空Int类型
age = null //只有当可空类型遇到null赋值,才会编译正常

  • 可以保护避免对可空类型的误操作:
//可以保护避免对可空类型的误操作
val address: String? = null //可空类型
println(address.length());//直接对可空类型操作,会编译错误,此时IDE会提示你这是可空类型变量,不能直接操作,你可能需要判断NPE的问题

  • 更安全的类型检测和类型转化:
//更安全的类型检测和类型转化
fun getStringLength(obj: Any): Int? {
if (obj !is String)
return null
//在这个分支中, obj的类型会被自动转换为String
return obj.length
}

2.3 互操作性

可以充分利用 JVM、Android 和浏览器的现有库。

  • 可以和 JVM 上的任何现有库有 100% 的兼容性:
//使用RxJava库
fetchUrlList()
.flatMap {
return@flatMap Observable.from(it)
}
.filter {
return@filter it.startWith("https")
}
.onErrorResumeNext {
return@onErrorResumeNext Observable.just("https://kotlinlang.org/")
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Observer<String> {
override fun onCompleted() {
//handle on onCompleted
}

override fun onError(e: Throwable) {
//handle on onError
}

override fun onNext(url: String) {
//handle on onNext
}
})

  • 可以和现有的 Android 库有很好的兼容性:
import android.graphics.Typeface
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.SpannedString
import android.text.style.StyleSpan
import android.text.style.UnderlineSpan
//Android API中的Spannable库的扩展函数
inline fun buildSpannedString(builderAction: SpannableStringBuilder.() -> Unit): SpannedString {
val builder = SpannableStringBuilder()
builder.builderAction()
return SpannedString(builder)
}

//实现混合Span样式-扩展函数inSpans
inline fun SpannableStringBuilder.inSpans(
vararg spans: Any,
builderAction: SpannableStringBuilder.() -> Unit
): SpannableStringBuilder {
val start = length
builderAction()
for (span in spans) setSpan(span, start, length, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)
return this
}

//实现加粗Span样式-扩展函数bold
inline fun SpannableStringBuilder.bold(builderAction: SpannableStringBuilder.() -> Unit) =
inSpans(StyleSpan(Typeface.BOLD), builderAction = builderAction)

//实现斜体Span样式-扩展函数italic
inline fun SpannableStringBuilder.italic(builderAction: SpannableStringBuilder.() -> Unit) =
inSpans(StyleSpan(Typeface.ITALIC), builderAction = builderAction)

//实现下划线Span样式-扩展函数underline
inline fun SpannableStringBuilder.underline(builderAction: SpannableStringBuilder.() -> Unit) =
inSpans(UnderlineSpan(), builderAction = builderAction)

//调用处
tv_des = buildSpannedString {
bold {
append("Kotlin")
}
append("是一门用于")
italic {
append("现代多平台应用")
}
underline {
append("静态编程语言")
}
}

  • 可以和JavaScript 平台有很好的兼容性,都可用 Kotlin 写代码然后部署到你想要的地方:
import kotlin.browser.window

fun onLoad() {
window.document.body!!.innerHTML += "<br/>Hello, Kotlin!"
}

2.4 工具友好

可以用任何 Java IDE 或者使用命令行构建。

图片描述

3. Kotlin能做什么?

如果对 Kotlin 的能力仅仅停留在 JVM平 台,那是片面的。如今的 Kotlin 已经从当初的更好 Java 目标完成了它华丽的大变身,他们的目标已经瞄准了星辰大海。目前 Kotlin 可以适用于移动端跨平台、原生 JVM、服务端开发、Web 开发、Android 开发、数据科学等多个领域。此外近年来 Kotlin 团队已经将重心转移到了语言层面的跨平台,多平台的支持。

图片描述

另一方面,Kotlin 得益于 Kotlin/JVM、Kotlin/JS、Kotlin/Native 三个语言编译器的后端实现,它不仅仅可以编译成 Java 字节码(Kotlin/JVM),也可以编译成JavaScript(Kotlin/JS),还能编译成直接运行在不需要任何VM平台的机器代码(Kotlin/Native),可以轻松实现语言层面的跨平台,并实现在多个平台之间共享代码。目前已经部分支持了Linux、Windows、macOS、WebAssembly、Android、iOS以及watchOS和tvOS平台

图片描述

4. 本教程能学到哪些 Kotlin 技能 ?

  • Kotlin的基本语法和代码规范 ;
  • Kotlin的面向对象;
  • Kotlin的函数式编程;
  • 扩展函数 ;
  • 属性代理 ;
  • 空指针类型安全 ;
  • 运算符重载 ;
  • lambda表达式和高阶函数;
  • 类型系统;
  • 泛型和型变 ;
  • 注解和反射 ;
  • 协程的基本使用;
  • Kotlin 的 DSL;
  • Kotlin 高效实现常用的设计模式;
  • Kotlin 在 Android、IntelliJ IDEA 插件、Gradle、服务端、Web、iOS 等实际应用开发。

5. 本教程适合哪些人群?

  • 零基础的开发者(会从编程语言的最基础开始讲起);
  • 有一定 Java、C 或 C++ 开发基础开发者想学习 Kotlin 开发;
  • Android 开发者想学习 Kotlin 开发 Android 应用;
  • Java 后端开发者想学习 Kotlin 开发后端应用;
  • 对 Kotlin 语言感兴趣的所有开发者。

6. 总结几条学习 Kotlin 的建议?

  • 如果有 Java 编程基础,记住千万不要用 Java 编程思维来写 Kotlin 代码,换句话说不要硬生生把 Java 代码转化成 Kotlin 代码来写,更需要换个思维想如果用 Kotlin 某个语法糖实现的话更优呢,否则将无法真正体会Kotlin这门语言精髓;
  • 记住要善于使用 Kotlin 中的反编译代码插件,就是将 Kotlin 代码反编译成 Java 代码。这是一条非常重要和实用的建议,通过它将会真正看透 Kotlin 语法糖背后原理,从而更高效地使用它;
  • 学会经常去看 Kotlin 源码实现,其实 Kotlin 源码很短的,当知道如何使用某个语法,更需要知道它背后原理以及善于总结它适用的场景;
  • 最后就是多多实践,最好是自己弄个实际的项目,从0到1全部使用 Kotlin 开发,每天一点一点给它舔砖加瓦,通过它来学习每一个 Kotlin 语法技能点。

7. 关于 Kotlin 的一些干货资料