Kotlin

Kotlin

基于Java基础快速入门Kotlin

使用命令行编译成jar包

1
kotlinc xx.kt -include-runtime -d xx.jar

运行 -jar …

输入输出

1
2
var a = readl()
println("结果是$a")

变量

val不可变

1
2
var 变量名: 变量类型 = 值
val 变量名: 变量类型 = 值

get() set()

1
2
3
4
5
6
7
8
9
10
var a: Int = 5
get() = field * 10
set(value){
println("我被赋值了")
field = value
}
fun main(){
println(a)
}

数字类型

Byte Short Int Long

127 32767 2^31-1 2^63-1 (max值)

Boolean

判断x是否在a与b之间

1
var y: Boolean = x in a..b

String

可以使用三引号 输出原始字符串 包括换行空格

1
2
3
4
5
6
//trimIndent 去除缩进
var b : String = """
111
222 333
555
""".trimIndent()

字符串拼接默认只能 字符串+其他类型 需要用占位符

1
2
var b = 10
var a = "${b}个数量"

if

没有三元运算符

1
var a = if (s>60) "Yes" else "No"  

when

类switch

1
2
3
4
5
6
7
8
9
10
when(a){
10 -> println("a is 10")
20 -> println("a is 20")
else -> println("a is not 10 or 20")
}
var c = when (b) {
'Q' -> 'q'
'W' -> 'w'
else -> 'E'
}

for

image-20250209124605327

1
2
3
4
5
6
//可以遍历 数组、区间、实现运算符重载函数iterator的类
var range = 1..10 step 2
for (i in range) {
println(i)
}

image-20250209125310339

while略

函数

1
2
3
4
5
6
7
fun 函数名(参数列表...): 返回类型{函数体}
//传参可以申明默认值
fun hello(a: Int = 10,b Int = 10): = a+b

fun main{
println(hello(b=10))
}

Unit类似Java的void可以省略

函数内部也可以定义函数

函数类型

Kotlin的函数可被变量存储,也就是说可以用变量接受函数

1
var func0(Int)->String //函数类型为Int返回值类型为String的函数

给函数类型起别名

1
typealias Text =  (Int)->String

使用lambda 函数里传参为函数的函数为高阶函数

1
2
3
var func: (String) -> Int = {it->10}
var func2: (String, String) -> Unit = {_,b-> println(b)}
func2("a","b")

image-20250209143930128

内联函数

inline

image-20250209144654122

类与对象

主构造函数没有注解和可见性修饰符可以省略 constructor 关键字

1
2
3
4
5
6
7
8
9
10
11
12
class Student(var width: Int, var height: Int) {
lateinit var name: String //懒加载 先不指定初始值
var age = 0
val area get() = width * height
constructor(name: String) : this(name,18) //次要构造函数 这里调用主构造函数
init{
println("初始化构造方法")
}
fun(){
println("成员方法")
}
}

kotlin 中的 === 相当于 java 中的 ==,kotlin 中的 == 相当于 java 中的 equals

运算符重载

image-20250209160139330

image-20250209161156299

中缀函数

infix关键字标记的函数为中缀函数,

条件: 必须是成员函数 只能有一个参数且不能有默认值

student.(“你好”) -> student test “你好”

空值和空类型

一般,在kotlin变量不能直接赋值为null

可空类型要在变量类型后面加?

在对象可能为空的情况下强制调用对象的方法要在后面加!!

?. 安全调用运算符

1
2
val student: Student? = null
println(student?.name ?: "我是为空的结果")

解构声明

在类里声明要解构的属性

1
2
3
4
class Student(val name: String, val age: Int) {
operator fun component1() = name
operator fun component2() = age
}

在主函数调用

1
2
3
4
5
6
7
8
9
10
11
fun main() {
var student = Student("小明",18)
val (name,age) = student
println("name:$name,age:$age")
var func: (Student) -> Unit = {
(a,b)->
println("a:$a,b:$b")
}
func(student)

}

继承

只能继承一个类

1
2
open class Student{}	//用open标记需要被继承的类
class ArtStudent: Student() {} //ArtStudent继承Student
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
open class Student( val name: String, val age: Int) {
init {
println("Student $name is $age years old")
}
open fun study() = println("Student $name is studying")
}
class SportStudent: Student {

constructor(name: String) : super(name, 20)
init {
println("SportStudent $name is $age years old")
}

override fun study(): Unit {
super.study()
println("SportStudent $name is studying") }
}
fun main() {
val sportStudent = SportStudent("John")
sportStudent.study()
}

类型强转 as Student

image-20250209175744185

Any类

所有类的顶级父类

抽象类 略

接口

1
2
3
4
5
6
7
8
9
10
interface A{
fun sleep = println("1")
}
interface B{
fun sleep = println("2")
}
interface C :A,B{}
class Student: A,B {
override fun sleep() = super<A>.sleep()
}

扩展类

可以通过可通过扩展类方法、属性强行扩展官方或第三方的类的功能

在哪里扩展 就只能在哪里的作用域使用

1
fun String.test = println("扩展了String类的test方法")

泛型

image-20250209193911149

image-20250209194405859

官方高阶扩展函数

apply 类似Java Builder

1
2
3
4
5
6
7
8
9
10
11
fun test01(student: Student?) : Student? {
student?.name = "小明"
student?.age = 18
student?.score = 100
return student
}
fun test02(student: Student?) : Student? = student?.apply {
name = "小明"
age = 18
score = 100
}

image-20250209200640110

1
2
3
4
val str = "Hello"
// 如果字符串长度大于5,则返回字符串拼接两次,否则返回原字符串
val myStr = str.takeIf { it.length > 5 }?.let { it->it+it }?:str
println(myStr)
1
2
3
4
//交换a,b的值
var a = 1
var b = 2
a = b.also { b = a }

斜变抗变逆变

image-20250209202110809

out 类似 ? extends xx

in 类似 ? super xx

就是Out只允许读出,生产者,In只允许写入,做消费者

泛型上界

image-20250209203555271

数组

定长

1
2
3
4
5
6
7
8
9
10
11
12
13
var array1:Array<Int> = arrayOf(1,2,3,4,5)
// 判断数组是否相等
println(array1.contentEquals(arrayOf(1, 2, 3, 4, 5)))
array1[0] = 10
println(array1.get(0))
// 数组拷贝
val array2: Array<Int?> = array1.copyOf(2)
val array3 = array1.copyOfRange(1, 3)
var array4 = array1+array3
println(array4.joinToString ())
array4.binarySearch(2)
fun test (vararg args: Int) = args.sum()
println(test(1,2,3,4,5))

image-20250209212700869

集合

image-20250209212932794

List

1
2
3
4
5
6
7
8
var list: List<Int> = listOf(1,2,3,4,5)// 不可变集合
var mutableList = mutableListOf(1,2,3,4,5)// 可变集合
val list1 = List(4,){ "2"}
for((index, value) in list1.withIndex()){
println("index: $index, value: $value")
}
mutableList.add(6)
mutableList.remove(1)

image-20250209214159976

Set

1
2
3
4
5
6
7
var set1 = setOf(1,2,3,4,5)// 不可变集合
var set2 = mutableSetOf(1,2,3,4,5)// 可变集合
var set3 = linkedSetOf(1,2,3,4,5)// 链表集合
var set4 = hashSetOf(1,2,3,4,5)// 不重复无序的集合
var set5 = sortedSetOf(1,2,3,4,5)// 排序集合
println(set1.contains(1))

Map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 键值对集合
val map1: MutableMap<Int, String> = mutableMapOf(1 to "a", 2 to "b", 3 to "c")
println(map1[1])
// 对键值对进行解构
val pair: Pair<Int, String> = 1 to "a"

//遍历
for(entry in map1){
entry.key
entry.value
}
for ((key, value) in map1) {
println("key: $key, value: $value")
}
map1.forEach { (key, value) -> println("key: $key, value: $value")}

map1 += Pair(4, "d")// 添加键值对
println(map1)
map1.putAll(mapOf(5 to "e", 6 to "f"))// 添加键值对
println(map1)
map1.remove(1)// 删除键值对
// 获取键值对 没有值时,返回默认值
map1.getOrDefault(7, "A")
map1.getOrElse(7,){ "A" }
// 获取键值对 没有值时,添加键值对并返回值
map1.getOrPut(7){ "A"}

image-20250209221249563

映射操作 map

image-20250209221746437

压缩 zip

image-20250209221903250

解压 unzip

associate操作

image-20250209222110683

image-20250209222141179

image-20250209222219962

可以用filter方法原地过滤集合 类似还有 filterNotNull() filterIsInstance()

分区操作

image-20250209222730863

更多操作

image-20250209223032678

序列

使用时才执行

image-20250209223538459

特殊类型

数据类型

image-20250209224124693

枚举类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
enum class LightState01{
RED,GREEN,YELLOW
}
enum class LightState02(val color: String){
RED("红灯"),GREEN("绿灯"),YELLOW("黄灯")
}
fun main(){
var light : LightState02 = LightState02.RED
// println(light.color) //红灯
val entries: EnumEntries<LightState02> = LightState02.entries // 获取枚举类的所有元素
for (entry in entries) {
println(entry.color)
}
val enumValues: Array<LightState02> = enumValues<LightState02>()
println(enumValues.joinToString())

}

匿名内部类

1
2
3
4
5
var obj = object {
val name = "张三"
override fun toString()= "我是内部类"
}
println(obj)

函数式接口

1
2
3
4
5
6
7
8
9
fun interface MyInterface { //函数式接口
operator fun invoke()
}
fun main() {
var myInterface = MyInterface {
println("test")
}
myInterface()
}

object还可以声明单例类

image-20250209232510687

委托模式

by

image-20250209233337437

成员变量 by lazy{} 实现懒加载

成员变量 by :: a(传参)

密封类型

自己的包不被别的包继承但可以调用

sealed

抽象的 无法被实例化 可以有抽象方法

image-20250209234427827

with 在对象实例上调用多个方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Turtle {
fun penDown()
fun penUp()
fun turn(degrees: Double)
fun forward(pixels: Double)
}

val myTurtle = Turtle()
with(myTurtle) { //draw a 100 pix square
penDown()
for (i in 1..4) {
forward(100.0)
turn(90.0)
}
penUp()
}

协程

协程,英文Coroutines,是一种基于线程之上,但又比线程更加轻量级的存在,协程不是被操作系统内核所管理,而完全是由程序所控制(也就是在用户态执行),具有对内核来说
不可见的特性。这样带来的好处就是性能得到了很大的提升,不会像线程切换那样消耗资源。

可以在同一个代码块多次切换线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//调度器
enum Dispatchers{
...
}

//用lauch开启协程用于启动一个不需要返回值的协程,适合执行一些后台任务或触发操作。
fun main(){
val job = launch(Dispatchers.Main){
//withContext指定线程并在执行完后切换回来
val image = withContext(Dispatchers.IO){
getImage(imageId)
}
...
}
job.join() //启动并等待线程完成
}

//用async开启协程通常用于需要返回值的协程,适合并发执行多个任务并等待结果
fun main() = runBlocking {
val deferred = async {
delay(1000)//等待10秒
"Result"
}
//async 返回一个 Deferred<T> 对象,可以通过 await() 获取结果。
println(deferred.await()) // 输出 "Result"
}

withContext函数需要在suspend函数下调用或者协程下使用

suspend函数——挂起函数 (非阻塞式)

暂时切换至别的线程,执行完后返回resume(恢复)线程

耗时的函数里加上suspend 修饰符和withContext()方法

与Java互操作注意

注意Java引用类型可空 Kotlin要用可空类型接受或者在Java变量上加上**@NotNull**使其不为空

Java能把String数组传给Object数组 Kotlin不行 原理 :数组 Java支持斜变Kotlin不支持

在Kotiln成员变量上加上**@JvmField**注解 就不会生成get set方法

在Kotlin顶端可以加上**@file:jvmName**(“名称”)自定义编译后的class名称

在Java使用Kotlin的单例对象需在类名后加上 .INSTANCE

在Java使用Kotlin的伴生对象需在外类名后加**.Companion**.内类名,也可以在Kotlin里给伴生对象加上**@JvmStatic注解编译成Java的静态方法**



新ICP备2025018290号-1
本站总访问量