Kotlin入门学习重点(与java不同之处)

kotlin学习资料

kotlin学习要点

函数式API(Lambda表达式)

语法结构

完整结构:
{参数1:参数类型,参数2:参数类型 ,..->函数体}
参数类型大多数可省略:
{参数1,参数2 -> 函数体}
Lambda只有一个参数,可用it代替参数,只保留函数体:
{it}
  • 当lambda表达式为函数的最后一个参数时,可将表达式移到括号外面;当仅有一个lambda表达式参数时,可将()省略。
    fun(lambda) <=> fun()lambda <=> fun lambda

空检测

加!!像Java一样抛出空异常,加?可不做处理返回值为 null或配合?:做空判断处理

  • obj?.do() 非空时执行 <=> if(obj!=null) obj.do()
  • a = obj?:b <=> a = if(obj!=null) obj else b
  • obj!!.do() 非空时执行,空时断言报错 <=> if(obj!=null) obj.do() else throws Exception

默认参数

/**
 * 默认参数 可选
 */
fun getUserInfo(name:String,age:Int ,sex:String="male",address:String)="姓名:$name  年龄:$age  性别:$sex  地址:$address"

//调用 有默认参数的可不传,没有默认值则必传  若默认参数不在最后,则必传
val res = getUserInfo("guchao",30,"male","焦作沁阳市")

//若不想传默认参数,但其后仍有参数,可通过键值对方式传参
val res = getUserInfo("guchao",30,address = "焦作沁阳市")

标准函数

  • with 场景:连续调用通一个对象的多个方法
val result = with(obj){
    ....
    "value" //最后一行是返回值
}
  • run 场景:同with,只是使用方式不一样,
val result = obj.run{
    //obj的上下文
    "value"  //最后一行是返回值
}
  • apply 场景:使用方式同run,但无法指定返回值,自动返回对象本身
val result = obj.apply{
    //obj的上下文
}
//result == obj
  • let 场景:使用方式同run,但不持有obj的上下文
val result = obj.let{
    //将obj对象传入 以it 可调用
    "value"  //最后一行是返回值
}
  • repeat 常见:将一件事重复n遍执行
repeat(n){
    //需重复执行的代码
}

定义静态方法

  • object 对象里的方法相当于静态方法
//Util.function() 即可调用
object Util{
    @JvmStatic
    fun function(){}
}
  • 通过半生对象定义静态方法(实质是Util类中伴生对象的实例方法)
//Util.function() 即可调用
class Util{
    companion object {
        @JvmStatic  //该注释会将方法编译成真正的静态方法
        fun function(){}
    }
}
  • 通过@JvmStatic注解定义(只能加在对象类 或伴生对象类中的方法上)
  • 顶层方法(类之外的方法)

关键字

  • 延时初始化 lateinit
class Demo{
    private lateinit var param:String //延迟初始化
    fun somemethod(){
        if(!::param.isInitialized){  //::param.isInitialized 来判断是否初始化过
            param = "HelloWorld"
        }
    }
}
  • 定义常量 const (const 只能在单例类、伴生对象或顶层方法中才能使用)
  • 密封类 sealed 好处:kotlin会自动检测密封类有哪些子类,并强制要求你将每个子类所对应的条件全部处理
//实现
sealed class Base()
class A :Base(){
}
class B :Base(){
}
//使用  不可能出现其他情况,必须实现Base所有子类所对应的条件
when(base:Base){
    A->...
    B->...
}
  • 运算符重载 operator 重新定义运算符的含义,实现对象的运算
//定义重载运算符的对象类
class Money(val value:Int){
    operator fun plus(money:Money):Money{
        val sum = value + money.value
        return Money(sum)
    }
}
  • a+b 调用 a.plus(b)
  • a-b 调用 a.minus(b)
  • a*b 调用 a.times(b)
  • a/b 调用 a.div(b)
  • a%b 调用 a.rem(b)
  • a++ 调用 a.inc()
  • a-- 调用 a.dec()
  • +av 调用 a.unaryPlus()
  • -a 调用 a.unaryMinus()
  • !a 调用 a.not()
  • a==b | a>b | a<b 调用 a.equals(b)
  • a>=b | a<=b 调用 a.compareTo(b)
  • a…b 调用 a.rangeTo(b)
  • a[b] 调用 a.get(b)
  • a[b]=c 调用 a.set(b,c)
  • a in b 调用 b.contains(a)

扩展函数

  1. 扩展函数语法
fun ClassName.methodName(param1:Int, param2:Int):Int{
        ...
    return 0
}

高阶函数

如果一个函数接收另一个函数作为参数,或返回值是另一个函数,那么该函数就是高阶函数。

  • 高阶函数
//定义高阶函数
fun operation(p1: Int, p2: Int, lambda: (Int, Int) -> Int?): Int? {
    return lambda(p1, p2)
}

//定义函数 加法
val plus: (Int, Int) -> Int = { a: Int, b: Int -> a + b } //Lambda表达式
//定义函数减法
fun minus(a:Int,b: Int):Int{
    return a-b
}
//使用
val res = operation(5, 6, plus) //函数变量
val res1 = operation(5,1,::minus) //::minus 表示函数引用
val res2 = operation(5, 6) { p1, p2 -> p1 * p2 } //直接传入lambda表达式
  • 内联函数(定义高阶函数时加上inline关键字声明即可)
//完全消除Lambda表达式带来的运行时开销
inline fun operation(p1: Int, p2: Int, lambda: (Int, Int) -> Int?): Int? {
    return lambda(p1, p2)
}
  • nionline与crossinline
//nionline 作用:内联高阶函数接收多个函数类型参数时,进行内联排除
inline fun inlineTest(block1:()->Unit,noinline block2:()->Unit){
}

//crossinline 作用:相当于契约,保证高阶函数的匿名类实现中不允许使用return关键字进行函数返回
inline fun runRunnable(crossinline block:()->Unit){//不使用crossinline,则会编译报错
    val runnable = Runnable{
        block()
    }
    runnable.run()
}

泛型

  • 定义泛型类
//类名后使用<>声明泛型
class MyClass<T>{
    fun method(param:T):T{
        return param
    }
}

//调用
val myClass = MyClass<Int>()
val result = myClass.method(110)
  • 定义泛型方法
//方法名前使用<> 声明泛型方法
fun <T> method(param:T):T{
    return param
}

//调用
val result = method<Int>(110)
  • 对泛型类型进行约束
fun <T:Number> method(param:T){
    return param
}

委托

  • 类委托
    精髓:将一个类的具体实现委托给另一个类去完成
//创建接口
interface Base{
    fun print()
}
//创建被委托的类
class BaseImpl(val x: Int) : Base {
    override fun print() { print(x) }
}
// 通过关键字 by 建立委托类
class Derived(b: Base) : Base by b

fun main(args:Array<String>){
    val b = BaseImpl(110)
    Derived(b).print() // 输出 110
}
  • 属性委托
/**
 * Created by guc on 2020/5/7.
 * 描述:属性委托
 */
class Delegate {
    var propValue:Any? = "default"

    /**
     * [any] 指定任何类都可以使用该代理
     * [prop] 属性操作类,可获取各种属性相关的值
     */
    operator fun getValue(any: Any?,prop:KProperty<*>):Any?{
        return propValue
    }
    /**
     * [any] 指定任何类都可以使用该代理
     * [prop] 属性操作类,可获取各种属性相关的值
     * [value] 赋给委托属性的值
     */
    operator fun setValue(any: Any?,prop:KProperty<*>,value:Any?){
        propValue = value
    }
}

infix函数

A to B <=> A.to(B)

//A.method(B)  等价于 A method B
infix fun String.beginWith(prefix: String) = startsWith(prefix)

string.beginWith(prefix) == string beginWith prefix

泛型的实化与泛型的协变

  • 泛型的实化允许获取泛型的实际类型(使用inline 和 reified 关键字)
inline fun <reified T> startActivity(context: Context,block: Intent.() -> Unit) {
    val intent = Intent(context, T::class.java)
    intent.block()
    context.startActivity(intent)
}
  • 泛型的协变
interface MyClass<T>{
    //in位置:参数位  out位值:返回位
    fun method(param:T):T
}
  • out T :T只能出现在out位置,相当于禁用了set方法
  • in T :T只能出现在in位置

协变:假如定义一个MyClass<T>的泛型类,其中A是B的子类,同时MyClass<A>又是MyClass<B>的子类型,那么我们就成MyClass在T这个泛型上的协变。
实现:MyClass<out T> 指定T只可出现在out位置(即泛型类在其泛型类型的数据上只读)

class SimpleData<out T>(val data:T?) {
    fun get(): T? = data
}
  • 泛型的逆变
    逆变:假如定义一个MyClass<T>的泛型类,其中A是B的子类,同时MyClass<B>又是MyClass<A>的子类型,那么我们就成MyClass在T这个泛型上的协变。
    实现:MyClass<in T> 指定T只能出现在in位置(即泛型类在其泛型类型的数据上只可写,不可读)
/* 
 * 描述:泛型类逆变
 */
interface Transformer<in T> {
    fun transform(t:T):String
}

协程

  1. 添加依赖
    //协程使用
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1'
  1. 基本用法
  • GlobalScope.launch {}//创建一个顶层协程,应用程序运行结束时也会跟着结束
  • runBlocking{} //保证在协程作用域内的所有代码和子协程全部执行完。阻塞当前线程
  • runBlocking{ launch{}…} //创建多个协程

注:suspend 可将函数声明为挂起函数,就可以调用其他挂起函数 delay()

suspend fun printDot(){
    println(".")
    delay(100)
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值