Kotlin使用总结

279 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情

  • Kotlin 中注解 @JvmOverloads 的作用?

    /**
    *在带有默认参数的方法中使用JvmOverloads,kotlin会为其生成多个重载方法(该注解一般使用在构造函数上简化构造模板代码)
    */
    class Person {
        @JvmOverloads
        constructor(name:String = "lsy",age:Int = 24,sex:Boolean = true)
    }
    //通过查看kotlin 反编译查看Java源码可以看到为其自动生成了3个构造方法,如下:
       @JvmOverloads
       public Person(@NotNull String name, int age) {
          this(name, age, false, 4, (DefaultConstructorMarker)null);
       }
    
       @JvmOverloads
       public Person(@NotNull String name) {
          this(name, 0, false, 6, (DefaultConstructorMarker)null);
       }
    
       @JvmOverloads
       public Person() {
          this((String)null, 0, false, 7, (DefaultConstructorMarker)null);
       }
    

    List和mutableList的区别在于List是只允许读而MutableList是允许读写的,并且通过反编译查看Java源码可以查看List最后会被反编译为EmptyList(是List的实现子类)只有读取权限,MutableList在反编译之后是ArrayList的实现

  • Kotlin 中实现单例的几种常见方式?

    /*加载类时创建*/
    object Xutils{
    	
    }
    //反编译成Java之后可以看到在Xutils第一次被加载时就会把对象给创建好,这样会拖慢整个启动进程
    public final class Xutils {
       @NotNull
       public static final Persons INSTANCE;
    
       private Persons() {
       }
    
       static {
          Persons var0 = new Persons();
          INSTANCE = var0;
       }
    }
    
    /*懒加载 需要的时候创建*/
    class Person {
        companion object {
            val instance by lazy(LazyThreadSafetyMode.NONE) {
                Person()
            }
        }
    }
    //同步锁写法
    class XUtils {
        companion object {
            private var instance: XUtils? = null
            @Synchronized
            fun get(): XUtils {
                if ( null == instance ) instance = XUtils()
                return instance as XUtils
            }
        }
    }
    //双重锁
    class Person {
        companion object {
            val instance by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
                Person()
            }
        }
    }
    //静态内部类的写法
    class XUtils private constructor(){
        companion object {
            val getInstance = Helper.instance
        }
        object Helper{
            val instance = XUtils()
        }
    }
    
  • 谈谈你对 Kotlin 中的 data 关键字的理解?相比于普通类有哪些特点?

    data关键字作为kotlin中声明数据类的关键字,在将此类声明为data class之后会自动为其属性生成getter和setter方法,以及toString(),equals(),hashCode()方法 ,相比较与普通类减少了一些模板代码的编写

    let

    --let块中如果最后一条语句为非赋值语句,则默认情况下它是返回语句,返回的是一个Unit类型

    --let可用于判空检查

    --可用于对结果链的结果进行操作

    --并且可以将it进行重命名为一个可读的lambda参数

    fun main(){
          val book = Book().let { book->   //在此可以将it进行重命名为book,代码块中便可以使用book进行参数访问
            book.name = "《计算机网络》"
            "This book is ${it.name}"
        }
        print(book)
    }
    /*控制台输出 This book is 《计算机网络》
     *如果语句块中最后一行不是赋值语句,这个时候控制台便会输出:kotlin.Unit
     
    

    run

    --和let相似最后一条语句块如果是非赋值语句,则默认情况下是返回语句,返回的是一个Unit类型

    --run适合用于lambda表达式中同时包含对象的初始化和返回值的计算

     val p = Person().run { 
         val a = ""
         print("$a $name")
    }
                
    

    with

    --with属于非扩展函数,直接输入一个对象receiver,当输入receiver后,便可以更改receiver的属性,同时,它也与run做着同样的事情。

    --with使用的是非null的对象,当函数块中不需要返回值时,可以使用with

    val p = Person()
    with(p){
        name = "Tony" //设置当前对象的name属性
        display()     //调用当前对象的display方法
    }
    

    apply

    --apply是T的扩展函数,并且提供空安全检查,和run的功能类似,但是差别在上下文的引用apply是this

    ,run是it,并且apply不接受lambda代码块中不接受函数的返回值,返回的是自己的T类型对象

    --应用场景:常常用于初始化对象或者是修改对象,因为它用于在不使用对象的函数的情况下返回自身

    val p = Person()?.apply {
         name = "demo"    //初始化对象  
    }
    

    also

    --also和apply功能相似只是上下文的引用改为了it,并且提供了可以将lambda参数重命名的功能

     val p = Person()
             .also { person ->person.name="" } //可以在此做对象的属性数据有效性的校验
             .name
    

    综合引用场景:

      **用于初始化对象或更改对象属性,可使用`apply`**
    
      **如果将数据指派给接收对象的属性之前验证对象,可使用`also`**
    
      **如果将对象进行空检查并访问或修改其属性,可使用`let`**
    
      **如果是非null的对象并且当函数块中不需要返回值时,可使用`with`**
    
      **如果想要计算某个值,或者限制多个本地变量的范围,则使用`run`**
    
  • Kotlin中 Unit 类型的作用以及与Java中 Void 的区别?

    Unit在Kotlin底层中是一个单例

    public object Unit {
        override fun toString() = "kotlin.Unit"
    }
    

    在kotlin中一切函数皆是表达式,在表达式中都是有返回值的,如果存在需要返回的数据,则需要将返回值声明为Unit(也可以省略)。和void差别在于void在Java中是一个关键字,但是Unit是一个类,并且可以省略,而Java则必须声明返回值类型

    Nothing

    在Kotlin当中,如果表达式能正常返回则需要将返回值正常声明为相应的数据类型,如果不能正常返回则需要将返回值声明为Nothing.