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); } }