
作为安卓开发的现任官方语言,Kotlin的名字取自于圣彼得堡旁边的一座小岛,就像其前任Java的名字取自于印度尼沙的一座小岛一样,暗示着自己准备将其取而代之的野心
与Java的互操作性
Java的势力广大,囊括了很多主流的安卓App和Library,想要诱使Java开发者们改宗必须做出一些妥协: Kotlin和Java代码可以互相调用,兼容已有的遗产代码; Kotlin可以让自己被编译成Java字节码,进而被JVM执行,实现与Java共享运行环境
类型系统
不像Java分primitive和reference类型,Kotlin贯彻着万物皆为对象的原则,将Any
/Any?
作为根类型被其他类型继承。除此之外,为了保持null安全性,Kotlin的类型分为可空类和非空类,一一对应
1 | val s1: String // 非空类型声明 |
访问可空表达式的属性和方法时需要在表达式后面加个问号
1 | val x: Int? = listOf(4444, null).random() |
使用埃尔维斯运算符?:
给可空的表达式加一个备用值
1 | println(listOf(4444, null).random() ?: 5555) |
当然保留了Java的三元运算符,不过换了一种形式
1 | println( if ( listOf(4444, null).random() ) 5555 else 6666) |
不同于Java,Kotlin中所有语句都可以写成表达式,给其分配一个值,不产生值的则会被分配一个特殊值Unit
,从属于Unit
类型,代表没有东西。
1 | println(if ( listOf(true, false).random() ) { } else { } ) // 回显kotlin.Unit |
函数作为对象也有自己的类型,可以直接被塞到变量里面然后调用
1 | val f: (Double, Double) -> Double = { x, y -> listOf(x,y).random() } |
Kotlin还可以根据初始表达式自动推断变量类型,免去声明的麻烦
1 | val x = "abc" // String |
变量和函数
变量和函数不必像Java一样必须在class里定义
1 | fun main() { |
传参的时候如果最后一个参数是函数可以用Block语法写在外面
1 | foo(2) { x -> x * x } |
扩展函数可以给已有的class扩展方法
1 | fun File.getWordlist() { |
自定义类
在class里val
/var
语句被用作定义属性,属性由field,initializer,getter以及setter组成,当然只读属性没有setter
1 | class C { |
如果getter和setter都只需要默认的,可以直接将属性写进原初构造函数里
1 | class C(val x: Int = 233) {} |
如果想在构造时做一些额外的事,可以使用init块以及次级构造函数,值得注意的是每个次级构造函数需要先调用原初构造函数
1 | class C(var x: Int) { |
执行的顺序是原初构造函数->每个属性的initializer->init块->次级构造函数
如果在声明一个属性的时候还没想好初始值,可以使用lateinit关键字告诉编译器”不用管这个反正我在用之前会初始化的”
1 | class C { |
在优化性能时如果想要把只读属性的初始化操作分散到不同的时间点中,可以使用懒初始化声明,让属性在被真正用到时再初始化
1 | class C { |
用伴生对象实现和类绑定的静态属性和方法
1 | class C { |
对于存放数据的类型,Kotlin贴心的提供了数据类,默认有着equals
,hashCode
,toString
符合直觉的方法实现以及构造函数
1 | data class C(var x: Int, var y: Int) { } |
最后是有着自定义固定值的Enum类
1 | enum class E { |
可见性修饰符
可见性修饰符可以用来限制变量,函数,类,以及方法的使用范围,不标记默认被当作public
public
: 无限制internal
: 只有同一模块可见protected
: 当前类以及子类可见private
: 对于类中声明,当前类可见,对于顶层声明,当前文件内可见