协程中的延迟Delay
//高仿协程中的延迟
suspend fun pkDelay(time: Long, unit: TimeUnit = TimeUnit.MILLISECONDS) {
suspendCoroutine<Unit> {
executor.schedule({
it.resume(Unit)
}, time, unit)
}
}
private val executor = Executors.newScheduledThreadPool(1) { runnable ->
Thread(runnable, "pk4pkThread").apply { isDaemon = true }
}
fun main() {
GlobalScope.launch(Dispatchers.IO) {
println("pkDelay start before")
pkDelay(//高仿协程中的延迟
// delay(100)
println("pkDelay start after")
}
Thread.sleep(10000)
}
协程监听取消
//协程监听取消
suspend fun getUserInfo(): String {
return suspendCancellableCoroutine { continuation ->
thread {
Log.d(TAG, "getUserInfo() called thread : ${Thread.currentThread().name}")
Thread.sleep(3000)
continuation.resume("this is userInfo result")
}
//监听取消 cancel
continuation.invokeOnCancellation {
Log.d(TAG, "getUserInfo() invokeOnCancellation called")
}
}
}
SAM 接口
//SAM 接口
fun interface TestInterface {
// fun test(ab: Int)
fun test()
}
Inner
class InnerClassTest {
fun get() {
val notInnerClass = NotInnerClass()
val innerClass = InnerClass()
}
//静态内部类
public class NotInnerClass
//内部类
public inner class InnerClass
}
伴生对象
//Kotlin 之所以能抛弃静态成员,主要原因在于它允许包级属性和函数的存在,
//而且 Kotlin 为了维持与 Java 完全的兼容性,为静态成员提供了多种替代方案:
//使用 包级属性和包级函数:主要用于 全局常量 和 工具函数 ;
//使用 伴生对象:主要用于与类有紧密联系的变量和函数;
//使用 @JvmStatic 注解:与伴生对象搭配使用,将变量和函数声明为真正的 JVM 静态成员。
class CompanionObject {
companion object {
const val name: String = ""
fun getAge(): Int {
return 10
}
@JvmField
val name2: String = ""//等效于 const val name2:String=""
@JvmStatic
fun getAge2(): Int { //
return 10
}
}
}
属性 Field
@file:JvmName("Field_Name") //java代码中就可以直接用Field_Name访问字段
package com.example.java
val name: String = "100" //包级属性 私有常量值 --> FieldKt.name
const val sex: Int = 0//包级属性 公共常量值 --> public static final int sex = 0;
//需要自定义 setter 或 getter 的属性,不能放在类头里定义,必须在类体内定义
//getter 是一个没有参数、返回类型与属性类型相同的函数
//setter 的参数列表一般有一个与属性类型相同的参数,没有返回值。
class Field {
val age: Int = 0// 成员属性 --> Field().age
}
类属性
//@Transient 这个关键字表示该属性是「瞬时」的,不参与类的序列化
//@Volatile 这个关键字用于多线程,可以视为「轻量化的 synchronized」
//@JvmField 这个关键字将 Kotlin 类的属性直接暴露出来,不生成getter方法,直接访问属性
//field : Backing Fields (幕后属性)
class PersonEntity(@JvmField val name: String, @Transient val age: Int) {
var likes:String="abc"
// get() {return likes+"dd"} // 错误的写法 -->递归调用内存溢出 Exception in thread "main" java.lang.StackOverflowError
get() {return field+"dd"} //正确的写法
val otherName get() = name + "_other"
}
构造函数 – 重载
class StudentEntity constructor(val name: String) {
//@JvmOverloads 重载构造函数,非必须的参数要设置默认值
//class StudentEntity @JvmOverloads constructor(val name: String, var age: Int=0,var sex: Int = 0) {
//lateinit修饰符只能修饰不可空类型,并且不允许修饰基础类型(四类八种基础类型int, double,boolean等)。
// lateinit var age: String //正确
// lateinit var age: String //错误
var age: Int = 0
//次构造函数不能在参数列表中声明并初始化成员变量,
//这也是“age: Int”前面为什么没有 val 的原因
constructor(age: Int, name: String) : this(name) {
this.age = age
CompanionObject.name
}
override fun toString(): String {
return "StudentEntity(name='$name', age=$age)"
}
}
改良 Elvis
/**
* 改良 Elvis
* Elvis 操作符很方便,但只能连接表达式,我们可以写一个扩展函数来作为加强版的 Elvis 操作符。
*/
inline infix fun <T : Any> T?.ifNull(block: (T?) -> T): T {
if (this == null) {
return block(this)
}
return this
}
使用
fun testIfNull() {
var testAny: String? = "jjj"
val resultStr = testAny ifNull {
val a = 1 + 2
println("a is $a")
"卧槽。。。2"
}
println("resultStr is $resultStr")
}
接口 Interface
//kotlin 接口可以有默认实现
//Kotlin 通过静态内部类 + 添加默认实现方法的方式实现了 JDK 1.6 中不支持的接口默认方法,给接口的设计带来了便利。
interface KotlinInterface {
fun getName(): String
fun getAge(): Int {//默认实现
return 1
}
}
//实现类 -- 实现接口方法
class KotlinInterfaceImpl : KotlinInterface {
override fun getName(): String {
return "KotlinInterfaceImpl"
}
}
//实现类 -- 复写默认实现
class KotlinInterfaceImpl2 : KotlinInterface {
override fun getName(): String {
return "KotlinInterfaceImpl2"
}
override fun getAge(): Int {
// return super.getAge()
return 2
}
}
Java实现kotlin的接口
public class KotlinInterfaceImpl3 implements KotlinInterface {
@NotNull
@Override
public String getName() {
return "KotlinInterfaceImpl3";
}
@Override
public int getAge() {
return DefaultImpls.getAge(this);//通过DefaultImpls调用默认的接口实现
}
}
小知识点测试
object MySomeTestClass {
@JvmStatic
fun main(args: Array<String>) {
//List 过滤操作
// val testList = listOf<String>("banner", "po", "KUI", "apply", "hello")
// testList.filter {
// it.length>2
// }.map {
// it.toUpperCase()
// }.forEach {
// println("it is $it")
// }
// //Map打印快捷方式
// val testMap = mapOf<String, String>(
// "a" to "a",
// "b" to "b",
// "c" to "c"
// )
// for ((S, K) in testMap) {
// println("S:$S K:$K")
// }
// var isNull: String? = null
// println(isNull?.toUpperCase()?.length ?: "KK")
//
// var oneValue: String? = "oneValue"
// println("oneValue let is ${oneValue?.let { transformValue(oneValue) }}")
// val mapped = oneValue?.let {
// transformValue(oneValue)
"---->let is return "
// } ?: "--->let is null"
// println("mapped is $mapped")
//Integer中 -128到127是常量值,所以装箱后===也相等,超过范围以外是非常量
// val a: Int = -128
// val boxedA: Int? = a
// val anotherBoxedA: Int? = a
//
// val b: Int = 127
// val boxedB: Int? = b
// val anotherBoxedB: Int? = b
//
// val c: Int = 128
// val boxedC: Int? = c
// val anotherBoxedC: Int? = c
// println(boxedA === anotherBoxedA) // true
// println(boxedB === anotherBoxedB) // true
// println(boxedC === anotherBoxedC) // false
// println()
// //===的另一种写法 equals
// println(boxedA?.equals(anotherBoxedA)) // true
// println(boxedB?.equals(anotherBoxedB)) // true
// println(boxedC?.equals(anotherBoxedC))// false
// println()
// // == 比较数值
// println(boxedA == anotherBoxedA) // true
// println(boxedB == anotherBoxedB) // true
// println(boxedC == anotherBoxedC) // true
//改良 Elvis
// var testAny: String? = "jjj"
// val resultStr = testAny ifNull {
// val a = 1 + 2
// println("a is $a")
// "卧槽。。。2"
// }
// println("resultStr is $resultStr")
// //无限递归调用,导致报错
// println("like is " + PersonEntity("", 1).likes)
// //循环 break 标签@ continue return
// //标签名@ 表达式 //标签名为合法的标识符,与变量名和函数名格式相同
// loop@ for (i in 1..10) {
// for (j in 1..100) {
// println("i is $i --> j is $j")
if (j == 10) break//终止最近的for循环-->这里是j循环
// if (j == 10) break@loop //终止 i 循环
// }
// }
//
// //Kotlin 为了简化程序,会给每个高阶函数添加一个 隐式标签,这个标签与函数同名
// val testList = listOf<Int>(1, 2, 3)
// val returnResult = testList.forEach {
// if (it == 2) return@forEach
// println("forEach it is $it")
// }
// println("returnResult is $returnResult")
// val returnResult2 = testList.let {
// return@let 1 //return@标签 返回值
// }
// println("returnResult2 is $returnResult2")
//invoke函数定义
// add(1, 3) {
// println("add it is $it")
// }
// //数据类型转变
// val testList = listOf(1, 2, 3)
// val destination = mutableListOf<String>()
// testList.mapTo(destination, {
// it.toString() + "_mapTo"
// })
// println("des is $destination")
}
//某种操作后转换
fun transformValue(value: String): Int? {
// return value.length
return null
}
//invoke() 函数定义了“调用”这个行为,它同时重载了括号操作符( () ),允许我们用括号来传入参数、得到返回值。
fun add(a: Int, b: Int, back: ((c: Int) -> Unit)) {
back(a + b)// 等价于 back.invoke(a + b)
}
}