@946898963
2020-07-09T08:16:30.000000Z
字数 2093
阅读 1182
Kotlin
在Java中我们在接口中定义了一个这样的方法

在Kotlin中实现时, 我们可以有2种实现方式

此时Kotlin被编译成的Java代码是这样的


此时Kotlin被编译成的Java代码是这样的

对比两种方案, 会发现, 多了三行代码

进入checkParameterIsNotNull方法内部, 会发现如果传入的对象是null的话是会直接抛出异常的

那么问题来了
如果我使用的是方案一
但是Java在调用onFinish方法时homeDesigner articleFeedList imageList 中的任意一个参数传入了null, 那么就会抛出throwParameterIsNullException

这样在Kotlin里实现一个Java定义的接口方法时会自动帮我们判断是否使用可空类型
使用as时如果转换失败则会直接抛出ClassCastException
使用as?时如果转换失败则会返回null
fun methodAsTest(list: List<*>) {val v = list[0] as Intprint(v) // 会Crash, 因为String无法转换成Intval v1 = list[0] as Int?print(v1) // 会Crash, 因为String无法转换成Int?val v2: Int? = list[0] as? Intprint(v2) // 会输出null, 因此虽然转换类型为Int// 但是v2需要为Int?val v3: Int? = list[0] as? Int?print(v3) // 会输出null, 原因同上}methodAsTest(listOf("Hello World"))// 正确的使用方法fun methodAsTest(list: List<*>) {// as转换前需要使用is来判断一下, 如果不想判断则请使用as?if (list[0] is Int) {val v = list[0] as Intprint(v)}if (list[0] is Int) {val v1 = list[0] as Int?print(v1)}val v2: Int? = list[0] as? Intprint(v2)val v3: Int? = list[0] as? Int?print(v3)}
结论: as转换前需要使用is来判断一下, 如果不想判断则请使用as?


// 构造的SynchronizedLazyImpl对象val i1: Int by lazy { 100 }// 构造的UnsafeLazyImpl对象val i2: Int by lazy(LazyThreadSafetyMode.NONE) { 100 }
**结论: ** 从图中我们可发现, 默认情况下by lazy构造的是线程安全的SynchronizedLazyImpl对象, 但是绝大多数情况下我们使用by lazy构造的对象都不涉及多线程调用, 因此, 如果你使用by lazy构造对象时, 如果确定不涉及到多线程时, 请加上LazyThreadSafetyMode.NONE参数
当你使用 kotlin-android-extensions 来解析布局文件时, 默认只支持 自定义View Fragment 和Activity , 在 ViewHolder 中使用 kotlin-android-extensions 时需要继承LayoutContainer.
// 方案一class CustomViewHolder(override val containerView: View): RecyclerView.ViewHolder(containerView), LayoutContainer// 方案二class CustomViewHolder(view: View): RecyclerView.ViewHolder(view), LayoutContainer {override val containerView: View?get() = itemView}
这样他才会在使用的时候会使用findCachedViewById方法来把View缓存起来, 否则他则会每次都使用findViewById方法, 这样ViewHolder就失去了他应有的价值
没问题: 我们需要手动指定observable中泛型的类型(即使编译器告诉我们可以省略, 也不能省略. 省略了就会报错, kotlin的bug)

有问题: 编译时会报错
