Kotlin / Java,字符串数组尚未在方法调用时初始化
在我的一个程序中,我得到了一个空的异常,并调试我发现这是因为我的String
数组 ( Java )之一:
val FRAGMENTS = arrayOf("phong-lighting", "phong-only", "blinn-lighting", "blinn-only")
还没有初始化时,我需要在一个连续的类方法 ( Java )中:
fun initializePrograms(gl: GL3) { programs = Array(LightingModel.MAX, { ProgramPairs( ProgramData(gl, "pn.vert", FRAGMENTS[it] + ".frag"), ProgramData(gl, "pcn.vert", FRAGMENTS[it] + ".frag")) }) unlit = UnlitProgData(gl, "pos-transform.vert", "uniform-color.frag") }
如果我把它移进去:
fun initializePrograms(gl: GL3) { val FRAGMENTS = arrayOf("phong-lighting", "phong-only", "blinn-lighting", "blinn-only") ... }
那么一切都很好..为什么?
Ps:同样的代码和相同的行为也在Java中
编辑:不要混淆,该init
不是class init
,它扩展框架方法在这里
Edit2: initializePrograms()
不会从超级构造函数中调用。 它从init(GL3 gl)
调用,它覆盖从Framework.init(GLAutoDrawable autoDrawable)调用的Framework.init(GL3 gl) ,应该从另一个线程开始一次调用Animator 。
原因
如果方法initializePrograms
在超类的构造initializePrograms
被调用,崩溃是一个预期的行为。 在构造对象之后,类的属性被初始化,所以在此之前它们是未初始化的。
在这种情况下,因为arrayOf
函数是内联函数,所以在反编译的类中清晰可见:
public final class Test { @NotNull private final String[] FRAGMENTS; ... public Test() { super(); String[] elements$iv = new String[]{"phong-lighting", "phong-only", "blinn-lighting", "blinn-only"}; Object[] var4 = (Object[])elements$iv; this.FRAGMENTS = (String[])var4; } }
请注意Test
类的构造函数以及在调用super()
之后如何初始化属性。
请注意,如果您要使用非内联函数来初始化该属性(例如listOf
),则初始化将与声明一起使用,但这实际上是相同的事情,而不是显式的。 在Java中,这个字段也将在构造函数完成后被初始化。
public final class Test { @NotNull private final List FRAGMENTS = CollectionsKt.listOf(new String[]{"phong-lighting", "phong-only", "blinn-lighting", "blinn-only"}); ... }
解
最有可能的是你想要达到的目标(考虑到所有的上限)是宣布然后作为一个静态的领域。 在Kotlin中,您可以通过将其嵌套到特定类的companion object
中来实现。
class Test { ... companion object { val FRAGMENTS = arrayOf("phong-lighting", "phong-only", "blinn-lighting", "blinn-only") } }
那么,就像你在反编译的类中看到的那样,它被声明为一个静态字段并且在static
块中初始化:
public final class Test { @NotNull private static final String[] FRAGMENTS; ... static { String[] elements$iv = new String[]{"phong-lighting", "phong-only", "blinn-lighting", "blinn-only"}; FRAGMENTS = (String[])((Object[])elements$iv); } }