美文网首页Android
【学习】Kotlin 复习笔记

【学习】Kotlin 复习笔记

作者: Merbng | 来源:发表于2021-05-18 17:56 被阅读0次

基础

  • ==和equal()相同,===比较内存地址
  • 顶级成员(函数&属性)的原理:
    Kotlin顶级成员的本质就是Java静态成员,编译后悔自动生成文件名Kt的类,也可以使用@Jvm:fileName注解修改自动生成的类名。
  • 默认参数的原理:
    Kotlin默认参数的本质是将默认值固化到调用位置,所以在Java中无法直接调用带默认参数的函数,
    需要在Kotlin函数上增加@JvmOverloads注解,指示编译器生成重载方法。
  • 解构声明的原理:
    Kotlin解构声明可以把一个对象的属性结构为一组变量,所以解构声明的本质就是局部变量。
val (name,price)=Book("Kotlin入门",66.6f)
println(name)
println(price)
------------------------------------------
Kotlin类需要声明`operator fun componentN()`方法来实现解构功能。
否则是不具备解构声明的功能的,例如:
class Book(var name:String,var price:Float){
    operator fun component1():String{//解构第一个变量
        return name
    }
    operator fun component2():Float{//解构第二个变量
        return price
    }
}
  • 扩展函数的原理:
    扩展函数的语义是在不修改类/不继承类的情况下,向一个类添加新函数或新属性。本质是静态函数,
    静态函数的第一个参数是接收者类型,调用扩展时不会创建适配对象或者任何运行时的额外消耗。
    在Java中,我们只需要像调用普通静态方法那样调用扩展即可。
  • 委托机制的原理:
    Kotlin委托的语法关键字是by,其本质上是面向编译器的语法糖,三种委托(类委托,对象委托,局部变量委托)在编译时都会
    转化为“无糖语法”。
    例如类委托:编译器会实现基础接口的所有方法,并直接委托给基础对象来处理。
    例如对象委托和局部变量委托:在编译时会生成辅助属性(prop$degelate),
    而属性/变量的getter()和setter()方法只是简单的委托给辅助属性的getValue()和setValue()处理。
  • 中缀函数:
    声明infix关键字的函数是 中缀函数,可以使用中缀表示法调用(忽略点和括号)
中缀函数的要求:
- 1. 成员函数活扩展函数
- 2. 函数只有一个参数
- 3. 不能使用可变参数或默认参数
举例:
infix fun String.吃(fruit:String):String{
    return "${this}吃${fruit}"
}
调用:“小名”吃 "苹果"

类型系统

  • 数值类型:
    Kotlin将基本数据类型和引用型统一为:Byte、Short、Int、Long、Float、Double、Char和Boolean。
    需要注意的是,类型的统一并不意味着Kotlin所有的数值类型都是引用类型,大多数情况下,它们在编译后会变成基本数据类型,
    类型参数会被编译为引用类型。
val b:Byte =1 // OK,字面值是静态检测的
val i:Int =b //错误
val i:Int = b.toInt()//ok

  • 只读集合 和 可变集合
    只读集合只可读,而可变集合可以增删改查(例如List只读,MutableList可变)
    需要注意,只读集合引用指向的集合不一定是不可变的,因为你使用的变量可能是众多指向同一个集合的其中一个。
  • Array 和 IntArray 的区别:
    Array<Int>相当于引用类型数组Integer[],
    IntArray相当于数值类型数组int[]

面向对象

  • 类修饰符
    Kotlin类/方法默认是final的,如果想让继承类/重写方法,需要在基类/基方法添加open修饰符
final: 不允许继承或重写
open:允许继承或重写
abstract:抽象类/抽象方法

  • 访问修饰符
    Java默认的访问修饰符是protected,
    Kotlin默认的修饰符是public
public:所以地方可见
internal:模块中可见,一个模块就是一组编译的Kotlin文件
protected:子类中可见(与Java不同,相同包不可见)
private:类中可见
  • 内部类
    Kotlin:默认为静态内部类,如果想访问类中的成员方法和属性,需要添加inner关键字称为非静态内部类;
    Java:默认为非静态内部类。

  • Object 与 companion Object 的区别
    object有两层语义:静态匿名内部类+单例对象
    companion object是伴生对象,一个类只能有一个,代表了类的静态成员(函数/属性)

  • object单例的原理

lambda表达式

  • lambda表达式本质上是[可以作为值传递的代码块],在老版本Java中,传递代码块需要使用匿名内部类实现,而使用lambda表达式甚至连函数声明都不需要,
    可以直接传递代码块作为函数值。

  • 当lambda表达式只有一个参数,可以用it关键字来引用唯一的实参

  • lambda表达式的种类
    1.普通Lambda表达式:例如()->R
    2.带接收者对象的lambda表达式:例如T.()->R

  • lambda表达式访问局部变量的原理:
    在Java中,匿名内部类访问的局部变量必须是final修饰的,否则需要使用数组或对象座一层包装。
    在Kotlin中,Lambda表达式可以直接访问非final的局部变量,其原理是提供了一层包装类,修改局部变量本质上是修改包装类中的值。

class Ref<T>(var value:T)
  • 内联函数的原理:
    lambda表达式编译后会变成匿名内部类,至少会生成一个中间对象,当lambda表达式被经常调用时,会增大运行开销,使用内联函数可以减少中间对象的开销,
    因为调用内联函数不会真正调用函数,而是把函数实现固化到函数调用的位置,需要注意:如果函数体太大就不适合使用内联函数了,因为会大幅度增加字节码大小。

  • 实化类型参数 reified:
    因为泛型擦除的影响,运行期间不清楚类型实参的实际类型,Kotlin中使用带实化类型参数的内联函数,可以突破这种限制,
    实化类型参数在插入到调用位置时会使用类型实参的确切类型代替,因此可以确定实参类型。

在这个函数里,我们传入了一个List,企图从中过滤出T类型的元素
Java:
<T>List<T>filter(List list){
    List<T> result =new ArrayList<>();
    for(Object e:list){
        if(e instanceof T){//compiler error
            result.add(e);
        }
        return result;
    }
}
---------------------------------
Kotlin:
fun <T> filter(list:List<*>):List<T>{
    val result =ArrayList<T>()
    for(e in list){
        if(e is T){//cannot check for instance of erased type:T
            result.add(e)
        }
    }
    return result
}
调用:
val list =listOf("",1,false)
val strList = filter<String>(list)
-----------------------------------------
内联后:
val result =ArrayList<String>()
for(e in list){
    if(e is String){
        result.add(e)
    }
}

协程

  • 协程的原理:使用同步代码编写异步程序

本文来自彭旭锐
查看原文

相关文章

网友评论

    本文标题:【学习】Kotlin 复习笔记

    本文链接:https://www.haomeiwen.com/subject/gmjyjltx.html