Kotlin 入门
Kotlin 语言简介
在 Android 系统诞生的前 9 年时间里, Google 都只提供了 Java 这一种语言来开发 Android 应用程序, 在 Android 1.5 系统中 Google 引入了 NDK 功能, 支持使用 C 和 C++ 语言来进行一些本地化开发.
Google 在 2017 年的 I/O 大会上宣布, Kotlin 正式成为 Android 的一级开发语言, 和 Java 平起平坐, Android Studio 也对 Kotlin 进行了全面的支持. 两年之后, Google 又在 2019 年的 I/O 大会上宣布, Kotlin 已经成为 Android 的第一开发语言, 虽然 Java 仍然可以继续使用, 但 Google 更加推荐开发者使用 Kotlin 来编写 Android 应用程序, 并且未来提供的官方 API 也将会优先考虑 Kotlin 版本.
Kotlin 是由 JetBrains 公司开发与设计的, 早在 2011 年, JetBrains 就公布了 Kotlin 的第一个版本, 并在 2012 年将其开源.
2016 年, Kotlin 发布了 1.0 正式版, 这代表着 Kotlin 已经足够成熟和稳定了, 并且 JetBrains 也在自家的旗舰 IDE 开发工具 IntelliJ IDEA 中加入了对 Kotlin 的支持, 自此 Android 开发语言终于有了另外一种选择.
2017年 Google 宣布 Kotlin 正式成为 Android 一级开发语言, Android Studio 也加入了对 Kotlin 的支持.
Android 操作系统明明是由 Google 开发的, 为什么 JetBrains 作为一个第三方公司, 却能够自己设计出一门编程语言来开发 Android 应用程序呢?
编程语言大致可以分为两类:
编译型语言和解释型语言. 编译型语言的特点是编译器会将我们编写的源代码一次性地编译成计算机可识别的二进制文件, 然后计算机直接执行, 像 C 和 C++ 都属于编译型语言. 解释型语言则完全不一样, 它有一个解释器, 在程序运行时, 解释器会一行行地读取我们编写的源代码, 然后实时地将这些源代码解释成计算机可识别的二进制数据后再执行, 因此解释型语言通常效率会差一些, 像 Python 和 JavaScript 都属于解释型语言.
虽然 Java 代码确实是要先编译再运行的, 但是 Java 代码编译之后生成的并不是计算机可识别的二进制文件, 而是一种特殊的 class 文件, 这种 class 文件只有 Java 虚拟机 (Android 中叫 ART, 一种移动优化版的虚拟机) 才能识别, 而这个 Java 虚拟机担当的其实就是解释器的角色, 它会在程序运行时将编译后的 class 文件解释成计算机可识别的二进制数据后再执行, 因此, 准确来讲, Java 属于解释型语言.
Java 虚拟机不关心 class 文件是从 Java 编译来的, 还是从 Kotlin 编译来的, 只要是符合规格的 class 文件, 它都能识别. 也正是这个原因, JetBrains 才能以一个第三方公司的身份设计出一门用来开发 Android 应用程序的编程语言.
Kotlin 的工作原理: 我现在开发了一门新的编程语言, 然后自己做了个编译器, 这个编译器将这门新的编程语言的代码编译成同样规格的 class 文件, Java 虚拟机同样能识别.
Kotlin 仅在 1.0 版本发布一年后就成为 Android 官方支持的开发语言.
Kotlin 的语法更加简洁, 对于同样的功能, 使用 Kotlin 开发的代码量可能会比使用 Java 开发的减少 50% 甚至更多. 另外, Kotlin 的语法更加高级, 相比于 Java 比较老旧的语法, Kotlin 增加了很多现代高级语言的语法特性, 使得开发效率大大提升. 还有, Kotlin 在语言安全性方面下了很多工夫, 几乎杜绝了空指针这个全球崩溃率最高的异常.
Kotlin 在拥有众多出色的特性之外, 还有一个最为重要的特性, 那就是它和 Java 是 100% 兼容的. Kotlin 可以直接调用使用 Java 编写的代码, 也可以无缝使用 Java 第三方的开源库. 这使得 Kotlin 在加入了诸多新特性的同时, 还继承了 Java 的全部财富.
运行 Kotlin 代码
运行一段Kotlin代码方法大概有以下 3 种.
第一种方法是使用 IntelliJ IDEA. 这是 JetBrains 的旗舰 IDE 开发工具, 对 Kotlin 支持得非常好. 在 IntelliJ IDEA 里直接创建一个 Kotlin 项目, 就可以独立运行 Kotlin 代码了. 但是这种方法的缺点是你还要再下载安装一个 IDE 工具.
新建项目:
使用 JDK:
项目自动创建了一个文件, 运行这个文件, 得到输出结果:
新建一个自己的 Kotlin 文件:
选择 File:
写一个最简单的 Kotlin 代码并运行这个代码:
第二种方法是在线运行 Kotlin 代码. 为了方便开发者快速体验 Kotlin 编程, JetBrains 专门提供了一个可以在线运行 Kotlin 代码的网站, 地址是: https://try.kotlinlang.org. 只要点击一下右上方的 Run 按钮就可以运行这段 Kotlin 代码了, 非常简单. 但是在线运行 Kotlin 代码有一个很大的缺点, 就是使用国内的网络访问这个网站特别慢, 而且经常打不开.
第三种方法是使用 Android Studio. 遗憾的是, Android Studio 作为一个专门用于开发 Android 应用程序的工具, 只能创建 Android 项目, 不能创建 Kotlin 项目. 但是没有关系, 我们可以随便打开一个 Android 项目, 在里面编写一个 Kotlin 的 main() 函数, 就可以独立运行 Kotlin 代码了.
在 HelloWorld 工程中, 找到这个位置, 新建一个 Kotlin 文件:
在这个 LearnKotlin 文件中编写一个 main() 函数:
package com.example.myapplication1 fun main() { println("Hello, Kotlin!!!") }
运行结果会在 Android Studio 下方的 Run 标签中显示.
变量
在 Kotlin 中定义变量的方式和 Java 区别很大, 在 Java 中如果想要定义一个变量, 需要在变量前面声明这个变量的类型, 比如说 int a 表示 a 是一个整型变量, String b 表示 b 是一个字符串变量. 而 Kotlin 中定义一个变量, 只允许在变量前声明两种关键字:val 和 var.
val(value 的简写)用来声明一个不可变的变量, 这种变量在初始赋值之后就再也不能重新赋值, 对应 Java 中的 final 变量.
var(variable 的简写)用来声明一个可变的变量, 这种变量在初始赋值之后仍然可以再被重新赋值, 对应 Java 中的非 final 变量.
仅仅使用 val 或者 var 来声明一个变量, 那么编译器怎么能知道这个变量是什么类型呢? 这也是 Kotlin 比较有特色的一点, 它拥有出色的类型推导机制.
Kotlin 每一行代码的结尾是不用加分号的.
程序示例:
fun main() { val a = 10 // 使用 val 关键字定义了一个变量 a, 并将它赋值为 10, 这里 a 就会被自动推导成整型变量 println("a = " + a) }
因为既然你要把一个整数赋值给 a, 那么 a 就只能是整型变量, 而如果你要把一个字符串赋值给 a 的话, 那么 a 就会被自动推导成字符串变量, 这就是 Kotlin 的类型推导机制.
但是 Kotlin 的类型推导机制并不总是可以正常工作的, 比如说如果我们对一个变量延迟赋值的话, Kotlin 就无法自动推导它的类型了. 这时候就需要显式地声明变量类型才行, Kotlin 提供了对这一功能的支持.
程序示例:
fun main() { // 显式地声明了变量 a 为 Int 类型, 此时 Kotlin 就不会再尝试进行类型推导了. // 如果现在你尝试将一个字符串赋值给 a, 那么编译器就会抛出类型不匹配的异常. val a: Int = 10 println("a = " + a) }
Kotlin 中 Int 的首字母是大写的, 而 Java 中 int 的首字母是小写的. 不要小看这一个字母大小写的差距, 这表示 Kotlin 完全抛弃了 Java 中的基本数据类型, 全部使用了对象数据类型. 在 Java 中 int 是关键字, 而在 Kotlin 中 Int 变成了一个类, 它拥有自己的方法和继承结构.
下表中列出了 Java 中的每一个基本数据类型在 Kotlin 中对应的对象数据类型.
Kotlin 之所以设计 val 关键字, 是为了解决 Java 中 final 关键字没有被合理使用的问题.
在 Java 中, 除非你主动在变量前声明了 final 关键字, 否则这个变量就是可变的. 然而这并不是一件好事, 当项目变得越来越复杂, 参与开发的人越来越多时, 你永远不知道一个可变的变量会在什么时候被谁给修改了, 即使它原本不应该被修改, 这就经常会导致出现一些很难排查的问题. 因此, 一个好的编程习惯是, 除非一个变量明确允许被修改, 否则都应该给它加上 final 关键字.
但是, 不是每个人都能养成这种良好的编程习惯. 因此, Kotlin 在设计的时候就采用了和 Java 完全不同的方式, 提供了 val 和 var 这两个关键字, 必须由开发者主动声明该变量是可变的还是不可变的.
那么我们应该什么时候使用 val, 什么时候使用 var 呢? 这里我告诉你一个小诀窍, 就是永远优先使用 val 来声明一个变量, 而当 val 没有办法满足你的需求时再使用 var. 这样设计出来的程序会更加健壮, 也更加符合高质量的编码规范.
函数
函数和方法就是同一个概念, 这两种叫法都是从英文翻译过来的, 函数翻译自 function, 方法翻译自 method, 它们并没有什么区别, 只是不同语言的叫法习惯不一样而已. 而 Java 中方法的叫法更普遍一些, Kotlin 中函数的叫法更普遍一些.
main() 函数就是一个函数, 只不过它比较特殊, 是程序的入口函数, 即程序一旦运行, 就是从 main() 函数开始执行的.
Kotlin 也允许我们自由地定义函数, 语法规则如下:
fun methodName(param1: Int, param2: Int): Int { return 0 }
首先 fun (function 的简写) 是定义函数的关键字, 无论你定义什么函数, 都一定要使用 fun 来声明.
紧跟在 fun 后面的是函数名.
函数名后面紧跟着一对括号, 里面可以声明该函数接收什么参数, 参数的数量可以是任意多个, 例如上述示例就表示该函数接收两个 Int 类型的参数. 参数的声明格式是 "参数名: 参数类型", 其中参数名也是可以随便定义的, 这一点和函数名类似. 如果不想接收任何参数, 那么写一对空括号就可以了.
参数括号后面的那部分是可选的, 用于声明该函数会返回什么类型的数据, 上述示例就表示该函数会返回一个 Int 类型的数据. 如果你的函数不需要返回任何数据, 这部分可以直接不写.
最后两个大括号之间的内容就是函数体了, 我们可以在这里编写一个函数的具体逻辑.
这就是定义一个函数最标准的方式了.
Kotlin 中还有许多其他修饰函数的关键字.
程序示例:
import kotlin.math.max fun largerNumber(num1: Int, num2: Int): Int { return max(num1, num2) }
上述代码中使用了一个 max() 函数, 这是 Kotlin 提供的一个内置函数, 它的作用就是返回两个参数中更大的那个数, 因此 largerNumber() 函数其实就是对 max() 函数做了一层封装而已.
程序示例:
import kotlin.math.max fun main() { val a = 10 val b = 20 val value = largerNumber(a, b) println("larger number: $value") } fun largerNumber(num1: Int, num2: Int): Int { return max(num1, num2) }
执行结果:
larger number: 20
当一个函数中只有一行代码时, Kotlin 允许我们不必编写函数体, 可以直接将唯一的一行代码写在函数定义的尾部, 中间用等号连接即可.
程序示例:
import kotlin.math.max fun main() { val a = 10 val b = 20 val value = largerNumber(a, b) println("larger number: $value") } // 一个 Kotlin 函数的语法糖. // 使用这种语法, return 关键字也可以省略了, 等号足以表达返回值的意思. fun largerNumber(num1: Int, num2: Int): Int = max(num1, num2)
Kotlin 出色的类型推导机制在这里也可以发挥重要的作用. 由于 max() 函数返回的是一个 Int 值, 而我们在 largerNumber() 函数的尾部又使用等号连接了 max() 函数, 因此 Kotlin 可以推导出 largerNumber() 函数返回的必然也是一个 Int 值, 这样就不用再显式地声明返回值类型了, 代码可以进一步简化成如下形式:
import kotlin.math.max fun main() { val a = 10 val b = 20 val value = largerNumber(a, b) println("larger number: $value") } // 一个 Kotlin 函数的语法糖. // 使用这种语法, return 关键字也可以省略了, 等号足以表达返回值的意思. fun largerNumber(num1: Int, num2: Int) = max(num1, num2)
这种语法糖还可以结合 Kotlin 的其他语言特性一起使用, 对简化代码方面的帮助很大.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库