Kotlin 例外情况“初始化错误”;指定为非空的参数为空";抽象类
我需要计算硬编码图像的Kotlin 例外情况“初始化错误”;指定为非空的参数为空";抽象类,kotlin,lazy-initialization,Kotlin,Lazy Initialization,我需要计算硬编码图像的hash abstract class ImageData { protected abstract val master: List<String> val data: Iterable<HexString> = master.map { s -> hex(s) } val hash: Int by lazy { master.fold(0) { hash, s -> 31
hash
abstract class ImageData {
protected abstract val master: List<String>
val data: Iterable<HexString> = master.map { s -> hex(s) }
val hash: Int by lazy {
master.fold(0) { hash, s ->
31 * hash + s.hashCode()
}
}
}
例外情况:
java.lang.ExceptionInInitializerError
at ....updateGraphics(Graphics.kt:162)
...
Caused by: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter $this$collectionSizeOrDefault
at kotlin.collections.CollectionsKt__IterablesKt.collectionSizeOrDefault(Iterables.kt)
at ....ImageData.<init>(ImageData.kt:17)
at ....FooImageData.<init>(FooImageData.kt:3)
at ....FooImageData.<clinit>(FooImageData.kt:3)
at ....updateGraphics(Graphics.kt:162)
删除lazy
不会消除问题
所有研究表明,参数的顺序可能是一个问题,但这里似乎不是这样——或者是这样
使用:
abstract class ImageData {
abstract val master: List<String>
// Yes I know the `get()` is unnecessary but for some weird reason that causes `hash` to crash.
val data: Iterable<HexString> get() = master.map { s -> hex(s) }
val hash: Int by lazy {
master.fold(0) { hash, s ->
31 * hash + s.hashCode()
}
}
}
抽象类ImageData{
摘要val主机:列表
//是的,我知道'get()'是不必要的,但由于某种奇怪的原因,它导致'hash'崩溃。
val数据:Iterable get()=master.map{s->hex(s)}
val hash:Int by lazy{
master.fold(0){hash,s->
31*hash+s.hashCode()
}
}
}
似乎解决了问题-不知道为什么
Kotlin版本最新稳定版(1.3)
目标JVM版本:
1.6
我认为关键区别在于get()
在data
属性上,再加上master
是抽象的。当构造这个基类时(在创建子类之前,因为子类的构造函数必须先调用超类的构造函数),基类初始化其所有成员。您的原始代码有以下行:
val data: Iterable<HexString> = master.map { s -> hex(s) }
val数据:Iterable=master.map{s->hex(s)}
这将获取master的值,此时该值为null,因为具体的子类尚未创建,因此无法重写该属性
在更新的代码段中,您有以下内容:
val data: Iterable<HexString> get() = master.map { s -> hex(s) }
val数据:Iterable get()=master.map{s->hex(s)}
在初始化抽象基类期间,data
属性现在不需要初始化(使用master
的值)。相反,当在运行时调用data
属性时,将执行get
函数。到那时,已经构造了具体的子类,可以为master
提供适当的值
有关这方面的更多详细信息,请参见:
因此,在设计基类时,应该避免使用open
构造函数、属性初始值设定项和init块中的成员
(
master
属性是abstract
,这意味着它是打开的
)有趣。。。但当数据
被初始化时,这个问题不会发生吗?在这里,当请求散列时,异常会发生在运行时。真的吗?有趣的我刚刚尝试了您的原始代码,并且在我的测试代码中的这一行中使用了FooImageData
后立即得到异常:val x=FooImageData
(即在我调用hash
之前)。你能分享显示它出错的完整代码吗?事实上,我认为你的错误堆栈跟踪也显示它在构造过程中发生:在…FooImageData.(FooImageData.kt:3)
(注意这里的init
函数,即在FooImageData
的初始化过程中).哦,我明白了-它在最后一分钟创建对象。
val data: Iterable<HexString> = master.map { s -> hex(s) }
val data: Iterable<HexString> get() = master.map { s -> hex(s) }