@946898963
2020-07-09T16:16:30.000000Z
字数 2093
阅读 932
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 Int
print(v) // 会Crash, 因为String无法转换成Int
val v1 = list[0] as Int?
print(v1) // 会Crash, 因为String无法转换成Int?
val v2: Int? = list[0] as? Int
print(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 Int
print(v)
}
if (list[0] is Int) {
val v1 = list[0] as Int?
print(v1)
}
val v2: Int? = list[0] as? Int
print(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)
有问题: 编译时会报错