持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情
-
/** *在带有默认参数的方法中使用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的实现
-
/*加载类时创建*/ 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.Unitrun--和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.