前言
Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,被称之为 Android 世界的Swift,由 JetBrains 设计开发并开源。苹果公司已经在用Swift语言替代Object-C语言,Google也找到了替代Java的语言,也就是JetBrains公司(Android Studio也是用该公司的Intelli J改的)主推的Kotlin。现在将kotlin作为了编写Android的官方语言
Kotlin在编写代码时有如下优势:
- 代码简洁高效
- Android Jetpack 与其他库中的 Kotlin 支持
- 可与 Java 的一起使用
- 空指针安全 *
基本语法
数据类型
不区分装箱非装箱类型,系统自动处理
Boolean、Number(Byte、Short、Int、Long、Float、Double)、Char
类型转换
xx.toX()
如“5”.toInt()as
对象类型的转换as?
转换失败,则为null
循环
- for循环
in until(不含最后一个) …(含最后一个)val array = arrayOf("3", "t", "d", 5) for (any in array) { } for (i in 0..array.size-1) { } for (i in 0 until array.size) { } for (i in array.indices) { }
- while循环
同java
when表达式
类似于switch,可以有返回值,可以是表达式判断
fun describe(obj: Any): String = when (obj) {
1 -> "A"
"a" -> "B"
is Long -> "C"
!is String -> "D"
is String -> "E"
is Int -> "F" //不会执行,要么是D,要么是E
else -> "Unknown"
}
ranges
使用 in (!in) 操作符检查数值是否在某个范围内
在范围内迭代:
for (x in arrayOf(1,2,3,4,5)) {
print(x) //1,2,3,4,5
}
for (x in 1..10 step 2) {
print(x) //1,3,5,7,9
}
for (x in 9 downTo 0 step 3) {
print(x) //9,6,3,0
}
数组,集合,map
数组
arrayOf()
、intArrayOf
…arrayOfNulls<Int>(5)
指定长度为5的数组- set get
array[index]
- 可变数组参数
String... ss
==vararg ss:String
集合
- 不可变集合
listOf() setOf() - 可变集合
mutableListOf() mutableSetOf()
使用in .contains() 检查集合中是否包含某个对象 ,in 判断的可用于when等场景
- 常用方法:
- 排序:
sorted
//元素升序排序
sortedBy
//对元素处理之后,再升序排序
sortedDescending
//元素降序排序
sortedByDescending
//对元素处理之后,再降序排序
sortedWith(object: Comparator{})
//重写compare方法,自定义规则排序 - 过滤
filter
filterNot
(filter取反)
filterIndexed { index, element -> index > element }
//过滤index,或者element
filterNotNull
//舍弃为null的元素
list1.filterIsInstanceTo(list2)
//将list1中属于list2的类型的元素添加进list2
- 排序:
list转化为map groupBy
map
遍历
for ((k, v) in map) {
print("$k -> $v")
}
习惯用语
-
数据类
data class Customer(val name: String, val email: String)
不可被继承,自动实现get,set(var变量),equal,hashCode,toString等方法 -
函数默认值
fun foo(a: Int = 0, b: String = "bbb",c: Int) {...}
使用:foo(a = 2, c = 7L)
,则b取定义的默认值 -
扩展函数
fun Class.fun(){}
如:
fun TextView?.setStyle(text: Int?) {
this?.text = (text ?: return).toString()
this?.textSize = 18f
}
调用方法tv.setStyle(5)
4. 创建单例模式
object Resource {
val name = "Name"
const val age = 18
}
-
只有一个表达式的函数
fun getAge() = 42
<==>fun getAge(): Int { return 42 }
-
with
调用一个对象实例的多个方法
fun TextView?.setStyle(text: Int?) {
with(this ?: return) {
this.text = (text ?: return).toString()
textSize = 18f
}
}
- use
Closeable对象调用,自动实现了close方法,在use方法体中写closeable的方法
val stream : InputStream! = Files.newInputStream(Paths.get("/some/file.txt"))
stream.buffered().reader()
.use { reader: InputStreamReader ->
println(reader.readText())
}
- in
- 判断某元素是否属于集合、数组等
- 判断某字符是否在字符串中
- 字符串模板
如:tv.setText("${a.toString()}”)
- 字符串"""的应用
会保留格式,转义\无效val s : String = """ q \n 啊 """.trimMargin() //移除空格
- break 和 continue 标签
aaa@ for (i in 1..10) {
bbb@ for (j in 2..5) {
if (j == 4) {
break@aaa
}
}
}
- is
等价于instanceof
!is
类
Any
是所有类的父类,Nothing
是所有类的子类- 所有的类默认是final,如果需要被继承,需要有open关键字
- 继承,实现均由于":"替代,继承的类
- 构造函数
在 Kotlin 中类可以有一个主构造函数以及多个二级构造函数。主构造函数是类头的 一部分:跟在类名后面(可以有可选的类型参数)。
class Person constructor(name: String) { }
如果主构造函数没有注解或可见性说明,则 constructor 关键字是可以省略:
class Person(name: String){ }
class A @SuppressLint("SetTextI18n") private constructor(context :Context)
初始化:
init {
}
- 只有open修饰的方法才能被重写,且一定有override关键字
变量的定义
- var(可读写) val(只读) (val等价于final)
- lateinit var 延迟初始化(因为在定义变量的时候必须有初始值)
- ? 表示可为空
- 变量的使用
- !! 表示非空,为空则空指针异常
- ? 表示可为空,如果为空则不执行 或者可用
- ?: 表示如果为空则取指定的冒号后的值
其他
-
“” 等价于 “equal”;“=” 等价于 “==”
-
set get统一 =
如:tv.setText("a")
=>tv.text = "a"
第4章 面向对象
4-1 面向对象-抽象类与接口(abstract,interface)
接口中可以定义对象,可以没有初始值
4-4 类及其成员的可见性(private,protected,internal,public)
internal
模块内可见
4-5 类的鼻祖-object
- 只有一个实例的类
- 不能自定义构造方法
- 可以实现接口、继承父类
- 本质上就是单例模式最基本的实现
4-6 伴生对象与静态成员
即 companion object
给伴生对象的方法加上@JvmStatic
或者对象@JvmField
之后,就可以在java中直接使用
4-7 方法重载与默认参数
方法重载(Overlords):方法名相同,参数不同
kotlin中,list有remove(object)
和removeAt(index)
两个方法,而在java中只有有remove(object/index)方法,如果是Integer
,则只能调用remove(index)
方法中参数可以有默认值,在java中使用的话,给该方法加上@JvmOverloads
即可以在java中调用用
4-8 扩展成员
扩展方法:String.aaa()
operator
关键字,即为重写操作符,如加减乘除
扩展属性:
不能初始化,类似于接口里的属性
val String.a: Int
get() = 5
4-9 属性代理
val a by lazy {
"aaa"
}
此处即a在第一次调用的时候才会被赋值为“aaa”
定义一个class类X,val a by X()
在X类中,需要实现operator fun getValue(,property: KProperty<*>)
方法
如果是var而不是val,则在X类中还需要实现operator fun setValue()
方法
4-10 数据类(allOpen,noArg插件,再见,javaBean)
知识点1
定义一个类对象的写法
val aaa = AAA(id = 1, name = "hello")
等价于
val (param1, param2) = AAA(id = 1, name = "hello")
这个param1, param2作为成员变量可以直接使用
aaa.component1()
即aaa.id
aaa.component2()
即aaa.name
备注(在Android中用不到,解决data没有无参方法和final的问题)
data class 默认是final,且没有无参构造方法(这里不符合javaBean的使用习惯,在其他地方可能有问题!)
解决(导入插件):
- project build.gradle
classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version"
- 定义 annotation class X
- 在module build.gradle中导入该注解X
apply plugin: 'kotlin-noarg'
apply plugin: 'kotlin-allopen'
noArg{
annotation("包名.X")
}
allOpen{
annotation("包名.X")
}
- 给该data类添加注解
@X
注意:因为是编译期生成的无参构造方法,所以写代码的时候(在编译期之前),依然无法直接定义 val aaa = AAA()
但是通过反射等可以拿到无参构造方法,所以数据库拿到该AAA之后可以当做javaBean使用
4-11 内部类(this@Outter,this@Inner)
- 静态内部类
- 非静态内部类(inner修饰)
获取对象的方式是Outer().Inner()
获取外部类的成员this@Outer.a
- 匿名内部类
object: IListener1, IListener2{ }
这里其实可以多继承或实现
4-12 枚举(enum)
enum class AAA()
可以添加方法,但是必须用“;”将枚举数据与方法分开
耗性能
4-13 密封类(sealed Class)
子类有限的类
子类必须与密封类在同一个文件中
子类作为该密封类的具体体现,与枚举类类比,枚举类是实例,密封类是类对象
如:
sealed class playerCommand{
class Play(val position: Long): playerCommand()
object Resume(): playerCommand()
}
第5章 高阶函数
5-1 *高阶函数的基本概念
- 传入或者返回函数的函数
- 函数引用 ::h
- 带有receiver的引用 a::h
class A {
fun f() {
}
}
访问到某方法的实例A::f
调用方式:
- 方法引用
::println
- 类名引用
String::isEmpty
- 类对象引用
a::println
8-1 与Java混合开发
- 自动识别getter/setter
- 常见注解使用
- @JvmField:将属性编译为Java变量
- @JvmStatic:将对虾干的方法编译成Java静态方法
- @JvmOverloads:默认参数生成重载方法
- @file:JvmName:指定Kotlin文件编译后的类名 - 泛型
java | kotlin |
---|---|
? | * |
List | List<*> |
- SAM(Single Abstract Method)
只有一个方法的接口,可以使用lamda表达式直接大括号
条件:Java的接口,只有一个接口方法
注意:使用的时候,大扩招中是新建一个对象,所以操作的不是同一个对象 - IO操作
同java,可使用 use,调用完成自动关闭流 - 注解处理器
- apply plugin:“kotlin-kapt”
- 添加生成的代码到sourceSets(module build.gradle)
sourceSets {
main.kotlin.srcDirs +="build/generated/souce/kapt/main"
}