本文参考Kotlin中文官网,官网写的很详细,是很好的入门参考资料。这篇文章主要是作为对官方文档的整理,不对原理做过多解释,方便新手快速入门。需要注意的是,你需要有java基础。
一、Kotlin是什么
Kotlin和java一样,是一门编程语言,运行在JVM之上,都需要经过编码——编译——执行的过程,不同的是java代码编译使用的是javac编译器,而kotlin代码使用的是kotlinc编译器。语言没有高低之分,只有使用场景和特性的区别。
二、Kotlin能做什么
kotlin完整包含java特性,所以java能做的kotlin都能做,比如服务器,Android开发。
三、实践
1、创建一个类
class MyClass {
}
这样声明的类默认是final的,无法被继承,要想开放继承,使用open
修饰符
open class MyClass {
}
kotlin没有new
关键字,创建对象直接使用 类名(参数)
的格式
val myClass = MyClass()
1.1、构造函数
java中的构造函数
public class MyClass {
// 无参构造器,默认。如果显式写出来,则会被带参构造器覆盖
public MyClass() {
}
// 带参构造器
public MyClass(String s) {
}
}
kotlin中一个类可以有一个主构造函数和一个或者多个次构造函数。如果主构造函数没有任何注解和可见性修饰符,则可省略constructor
关键字
// 主构造函数
class MyClass constructor() {
}
// 次构造函数
class MyClass {
constructor() {
}
}
// 没有注解和修饰符的著构造函数
class MyClass() {
}
如果有注解或者可见性修饰符,则constructor
关键字不能省略,且这些注解和修饰符在它前面
// 有注解和修饰符的主构造函数不能省略constructor关键字
class MyClass private @Inject constructor() {
}
如果类有一个主构造函数,那么次级函数都要直接或间接委托给主构造函数,使用this
关键字
// kotlin
class MyClass constructor() {
constructor(s: String): this() {
}
}
// 或者
class MyClass() {
constructor(s: String): this() {
}
}
如果需要在类中进行初始化,使用init
关键字修饰的初始化代码块,
class MyClass() {
init {
// init job1
}
init {
// init job2
}
...
}
初始化代码块是主构造函数的一部分,因此所有初始化代码块都会在主构造函数中优先执行,其次才会执行次构造函数中的代码。
1.2、变量
var
:修饰可变量
val
:修饰不可变量
成员变量可以和java一样,在类体内声明,注意此时声明变量是必须初始化(或使用lateinit
关键字懒初始化)
// 必须初始化
class MyClass {
lateinit var s1: String
val s2: String = "S2"
}
也可以在主构造器中声明,此时可以不初始化
// 可以不初始化
class MyClass constructor(
var s1: String,
val s2: String = "S2"
) {
}
// 或者
class MyClass(
var s1: String,
val s2: String = "S2"
) {
}
使用类型推断,可以把类型去掉,变成
var s1 = "S1"
1.3、函数
1.3.1、具名函数
使用fun
关键字声明
fun getName(): String {
return name
}
区别于java,返回类型在函数声明后面,用:
隔开,如果没有返回值,用Unit
接收,可以省略不写。上面函数还可以简化为单表单表达式函数
fun getName(): String = name
// 或简化为
fun getName() = name
1.3.2、匿名函数
顾名思义就是没有名字的函数,比如下面这种写法
private fun getName() {
// 变量name接收匿名函数,name表示一个函数,需要两个Int类型入参,返回Int
val name: (Int, Int) -> Int = { a: Int, b: Int ->
a+b
}
// 调用name函数,传入1,2作为参数,函数结果传递给value
val value: Int = name(1, 2)
println(value)
}
// 以上函数调用部分可以直接写成这样
{ a: Int, b: Int ->
a+b
}(1, 2)
注意,匿名函数如果有返回值,一般不用
return
,函数体中最后一行的结果默认作为返回值。匿名函数只能出现在其他函数体中,不能独立存在。更多具名函数和匿名函数的介绍,参考这篇文章
Kotlin学习笔记函数篇(1)具名函数和匿名函数
1.3.3、局部函数
kotlin支持局部函数,即一个函数在另一个函数内部
fun getName(s1: String) {
fun setName(s2: String) {
println(s1)
}
}
成员函数可以访问外部函数(闭包)的局部变量。
2、内部类
这部分和java基本相同,在kotlin中普通内部类(也叫嵌套类)默认是static的,不持有外部类引用,
class Outer {
class Nested {
}
}
使用inner
关键字修饰,那么就不是static的,会持有外部类对象的引用
class Outer {
private val s: String = "S"
inner class Nested {
println(s)
}
}
匿名内部类
Android中会经常写如下代码
mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// click event
}
});
使用kotlin可以这样写
mView.setOnClickListener(object: View.OnClickListener {
override fun onClick(view: View) {
// click event
}
})
3、集合
3.1、构造集合
可以完全使用Java创建集合的方式,比如
val list = ArrayList<String>()
val map = HashMap<Int, String>()
val set = HashSet<String>()
val sparseArray = SparseArray<String>()
也可以使用kotlin原生库,比如
val list = arrayListOf<String>()
val map = hashMapOf<Int, String>()
val set = hashSetOf<String>()
// SparseArray没有kotlin原生构建方式
val sparseArray = SparseArray<String>()
在构造集合的同时可以初始化,
val list = arrayListOf<String>("1", "2", "3")
3.2、遍历集合
3.2.1、forEach
val list = arrayListOf<String>()
list .forEach { s ->
println(s)
}
val map = hashMapOf<Int, String>()
map .forEach { entry ->
println("${entry .key} -> ${entry .value}")
}
3.2.2、for
val list = arrayListOf<String>()
for (s in list) {
println(s)
}
val map = hashMapOf<Int, String>()
for (entry in map ) {
println("${entry.key} -> ${entry.value}")
}
3.2.3、iterator
val list = arrayListOf<String>()
val iterator = list .iterator()
while (iterator.hasNext()) {
println(iterator.next())
}
val map = hashMapOf<Int, String>()
val iterator = map .iterator()
while (iterator.hasNext()) {
val entry = iterator.next()
println("${entry.key} -> ${entry.value}")
}
4、条件判断
4.1、if else
用法上kotlin基本和java一致,不同的是,koltin中if else是可以有返回值的,比如
val value = if (条件一) {
"这是条件一的返回值"
} else {
"这是else的返回值"
}
if else条件代码块中最后一行代码的结果会默认作为整体的返回值。另外,由于kotlin没有三目运算符,所以可以用if else来提代。
4.2、when
kotlin中的when
对应java中的switch case
when (条件) {
匹配值1 -> {
println("这是匹配值1的结果")
}
匹配值2 -> {
println("这是匹配值2的结果")
}
匹配值3 -> {
println("这是匹配值3的结果")
}
...
else -> {
println("这是没有匹配到的结果")
}
}
同样,when
也可以作为表达式来使用,返回的是条件代码块中最后一行代码的执行结果
val value = when (条件) {
匹配值1 -> {
"这是匹配值1的结果"
}
匹配值2 -> {
"这是匹配值2的结果"
}
匹配值3 -> {
"这是匹配值3的结果"
}
...
else -> {
"这是没有匹配到的结果"
}
}
5、空判断
kotlin中默认参数不能为null,在声明一个变量的时候需要初始化,如果定义的变量可以为null,使用?
进行标识
val s: String = "S" // 必须初始化,且不能为null
var s1: String? = null // 必须初始化,但可以为null
如果一个变量在声明的时候无法初始化,但又不能为null,此时可以用lateinit
来修饰,
lateinit var s3: String // 声明时不必初始化,不可null
注意,lateinit
修饰的变量可以不在声明时初始化,但定要在使用前进行初始化,否则会抛异常。
6、作用域函数
作用域函数唯一的作用就是在对象的上下文中执行代码块,也就是说这个作用域指的就是对象的上下文。作用域函数一共5种:let
、run
、with
、apply
以及 also
。作用域函数的详细介绍参考Kotlin学习笔记_作用域函数