ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Kotlin(3)-协程和操作符重载,java技术经理

2021-12-05 13:07:00  阅读:162  来源: 互联网

标签:异步 协程 Kotlin 重载 操作符 fun java 执行


launch {
delay(1000)
finalRes = finalRes.plus(“1”)
}
launch {
delay(2000)
finalRes = finalRes.plus(“2”)
}

launch {
delay(3000)
finalRes = finalRes.plus(“3”)
}
}
finalRes
}

fun main() {
val test6 = test6()
println(“最终返回值是: $test6”)
}

最终返回结果为(延迟3秒之后打印):

最终返回值是: 123

  • 如果有一个函数,需要顺序执行多个网络请求,并且后一个请求依赖前一个请求的执行结果

import kotlinx.coroutines.*

suspend fun getToken(): String {
for (i in 0…10) {
println(“异步请求正在执行:getToken :$i”)
delay(100)
}
return “ask”
}

suspend fun getResponse(token: String): String {
for (i in 0…10) {
println(“异步请求正在执行:getResponse :$token $i”)
delay(100)
}

return “response”
}

fun setText(response: String) {
println(“setText 执行,时间: ${System.currentTimeMillis()}”)
}

fun main() {
GlobalScope.launch(Dispatchers.Unconfined) {
var token = GlobalScope.async(Dispatchers.Unconfined) {
return@async getToken()
}.await() // 创建异步任务,并且 阻塞执行 await 是阻塞执行取得结果

var response = GlobalScope.async(Dispatchers.Unconfined) {
return@async getResponse(token)
}.await() // 创建异步任务,并且立即执行

setText(response)
}

Thread.sleep(20000)
}

执行结果:

异步请求正在执行:getToken :0
异步请求正在执行:getToken :1
异步请求正在执行:getToken :2
异步请求正在执行:getToken :3
异步请求正在执行:getToken :4
异步请求正在执行:getToken :5
异步请求正在执行:getToken :6
异步请求正在执行:getToken :7
异步请求正在执行:getToken :8
异步请求正在执行:getToken :9
异步请求正在执行:getToken :10
异步请求正在执行:getResponse :ask 0
异步请求正在执行:getResponse :ask 1
异步请求正在执行:getResponse :ask 2
异步请求正在执行:getResponse :ask 3
异步请求正在执行:getResponse :ask 4
异步请求正在执行:getResponse :ask 5
异步请求正在执行:getResponse :ask 6
异步请求正在执行:getResponse :ask 7
异步请求正在执行:getResponse :ask 8
异步请求正在执行:getResponse :ask 9
异步请求正在执行:getResponse :ask 10
setText 执行,时间: 1578904290520

  • 当前正在执行一项异步任务,但是你突然不想要它执行了,随时可以取消

fun main() {
// 协程任务
val job = GlobalScope.launch(Dispatchers.IO) {
for (i in 0…100){// 每次挂起100MS,100次也就是10秒
println(“协程正在执行 $i”)
delay(100)
}
}

// 但是我在1秒之后就取消协程
Thread.sleep(1000)
job?.cancel()
println( “btn_right 结束协程”)
}

执行结果(本该执行100轮的打印,只持续了10轮):

协程正在执行 0
协程正在执行 1
协程正在执行 2
协程正在执行 3
协程正在执行 4
协程正在执行 5
协程正在执行 6
协程正在执行 7
协程正在执行 8
协程正在执行 9
btn_right 结束协程

Process finished with exit code 0

  • 如果你想让一个任务最多执行3秒,超过3秒则自动取消

import kotlinx.coroutines.*

fun main() = runBlocking {
println(“限时任务中结果是:” + getResFromTimeoutTask())
}

suspend fun getResFromTimeoutTask(): String? {
// 忘了,它会保证内部的协程代码都执行完毕,所以不能这么写
return withTimeoutOrNull(1300) {
for (i in 0…10) {
println(“I’m sleeping $i …”)
delay(500)
}
“执行结束”
}
}

执行结果

I’m sleeping 0 …
I’m sleeping 1 …
I’m sleeping 2 …
限时任务中结果是:null

Process finished with exit code 0

总结

协程作为kotlin 区别于java的新概念,它的出现是为了解决java不好解决的问题,比如层层回调导致代码臃肿,比如 异步任务执行流程不好操控等。本章节篇幅有限,无法展开说明,但是对于新手而言,看完本章应该能对协程的作用有一个大概的认知。本人也是初步研究,后续有更深入的了解之后,再进行专文讲解吧。


操作符重载

概念

说人话,像是一元操作符 ++自加,二元操作符 +相加 ,默认只支持数字类型,比如Int. 但是通过操作符的重载,我们可以让任意类 都能 ++自加,且返回一个想要的对象。操作符执行的逻辑,完全看我们如何去设计。

分类

按元素级别

  • 一元
表达式对应函数
+aa.unaryPlus()
-aa.unaryMinus()
!aa.not()
a++a.inc()
a–a.dec()
  • 二元
表达式对应函数
a+ba.plus(b)
a-ba.minus(b)
a*ba.times(b)
a/ba.div(b)
a%ba.rem(b)
a…ba.range(b)
a in bb.contains(a)
a !in b!b.contains(a)
a[i]a.get(i)
a[i,j]a.get(i,j)
a[i_1,…,i_n]a.get(i_1,…,i_n)
a[i]=ba.set(i,b)
a[i,j]=ba.set(i,j,b)
a[i_1,…,i_n]=ba.set(i_1,…,i_j,b)
a()a.invoke()
a(i)a.invoke(i)
a(i,j)a.invoke(i,j)
a(i_1,…,i_n)a.invoke(i_1,…,i_n)

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

| a+=b | a.plusAssign(b) |
| a-=b | a.minusAssign(b) |
| a*=b | a.timesAssign(b) |
| a/=b | a.divAssign(b) |
| a%=b | a.modAssign(b) |
| a > b | a.compareTo(b)>0 |
| a < b | a.compareTo(b)<0 |
| a>=b | a.compareTo(b)>=0 |
| a<=b | a.compareTo(b)<=0 |

按实现方式

  • 成员函数

  • 扩展函数

栗子

看到上面的一大堆,肯定有点懵,看个例子解决疑问。上面我用两种维度来对操作符重载进行了分类,那么,先试试:成员函数的方式来重载一个一元操作符

class A(i: Int, j: Int) {
var i: Int = i
var j: Int = j
/**

  • 重载++操作
    */
    operator fun inc(): A {
    return A(i++, j++)
    }
    override fun toString(): String {
    return “[i= i , j = i , j= i,j=j]”
    }
    }

如上代码,注意看:

operator fun inc(): A {
return A(i++, j++)
}

Kotlin的操作符重载和 c++,dart语言内的操作符重载写法完全不同,它不再是直接把操作符放到了 重写的过程中,而是每一种支持重载的操作符都有一个对应的 函数名

正如:上表格中的 a++ 操作符,对应的函数就是 a.inc()

调用的时候:

fun main() {
var a = A(1, 2)
println(“a: a " ) p r i n t l n ( " a + + : a") println("a++: a")println("a++:{a++}”)
}

打印结果:

a:[i=1 , j=2]
a++:[i=2 , j=3]

再看一个二元运算符重载的栗子,这次我们不用成员函数,而是用扩展函数:

class A(i: Int, j: Int) {
var i: Int = i
var j: Int = j
override fun toString(): String {
return “[i= i , j = i , j= i,j=j]”
}
}
/**

  • 重载A类的 x+y 操作
    */
    operator fun A.plus(a: A): A {
    return A(this.i + a.i, this.j + a.j)
    }
    fun main() {
    val x = A(1,1)
    val y = A(2,2)
    println(x+y)
    }

这里演示的是 A类的 x+y 操作符重载。细节应该不用多说。

打印结果:

[i=3 , j=3]

再来一个较为复杂的栗子, 重载 a[i]

/**

  • 比如,B类中有一个成员,list,我想重载操作符,直接取到list中的元素
    */
    class B {
    val list: MutableList = mutableListOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
    }
    //a[i]
    operator fun B.get(i: Int): Int {
    return list[i]
    }
    fun main() {
    val b = B()
    println("${b[2]}")
    }

打印结果:

3

最后一个栗子:a > b,对应函数为:a.compare(b)

/**

  • 学生class
    */
    data class Student(val math: Int = 0, val chinese: Int = 0, val english: Int = 0)

fun Student.toString():String{
return “[math: m a t h c h i n e s e : {math} chinese: mathchinese:{chinese} english:${english}]”
}
fun Student.totalScore(): Int {
return math + chinese + english
}

/**

  • 比如,我们要直接比较两个学生的总分
    */
    operator fun Student.compareTo(s: Student): Int {
    return this.totalScore() - s.totalScore()//比较2个学生的总分
    }

fun main() {
val s1 = Student(math = 50, chinese = 90, english = 100)
val s2 = Student(math = 80, chinese = 70, english = 60)

println(“s1: s 1 " ) p r i n t l n ( " s 2 : {s1}") println("s2: s1")println("s2:{s2}”)
//比如存在这两个学生,我要知道他们的总分谁高谁低
println(“学生s1,s2的总分:${if(s1 > s2) “s1比较高” else “s2比较高” }”)

}

打印结果:

s1:Student(math=50, chinese=90, english=100)
s2:Student(math=80, chinese=70, english=60)
学生s1,s2的总分:s1比较高

总结

通过以上几个栗子,应该能看出,kotlin的操作符重载,编码和使用都十分简单。重载之前需要确定两件事

  • 根据业务需求,确定要重载的是哪一个操作符,虽然操作符的最终执行逻辑完全由我们自定义,但是我们重载操作符的目的是为了 让使用者更简单的理解业务代码,所以,要选择原本意义更加符合业务需求的操作符。Kotlin支持的操作符在上述表格中都列举出来了,支持大部分一元二元操作符,但是二元中不支持===的重载,不支持三元操作符bool?a:b这种 。
  • 确定重载函数的 入参类型个数,以及返回值类型,并且编写操作符的执行逻辑。

Hi~ o(* ̄▽ ̄ *)ブ

疫情无情,人有情!

####小编宅家期间整理了约 300G 关于BATJ大厂的面试资料

标签:异步,协程,Kotlin,重载,操作符,fun,java,执行
来源: https://blog.csdn.net/m0_64867003/article/details/121727952

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有