尝试访问继承字段时发生NullPointerException

在尝试访问父类中的重写变量时,我正在获取NPE

java.lang.NullPointerException: Attempt to get length of null array at app.deadmc.materiallivewallpaper.model.Square.<init>(Square.kt:29) at app.deadmc.materiallivewallpaper.model.Cube.<init>(Cube.kt:8) at app.deadmc.materiallivewallpaper.renderer.MaterialRenderer.onSurfaceCreated(MaterialRenderer.kt:40) at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1548) at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1286) 

我将展示简化的代码,以解决未知的问题

我有一个绘画广场的课

 open class Square(renderer: ReadyRenderer) { val COORDS_PER_VERTEX = 3 open val triangleCoords = floatArrayOf( //first triangle -1.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, //second triangle -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f) private val vertexCount:Int = triangleCoords.size / COORDS_PER_VERTEX init { val bb = ByteBuffer.allocateDirect( triangleCoords.size * 4) //other code } } 

广场正常工作,但现在我想绘制立方体,所以我只是从方形继承,并添加更多的坐标

 open class Cube(renderer: ReadyRenderer):Square(renderer) { val size = 1.0f override val triangleCoords = floatArrayOf( //front side // Triangle 1 -size, size, size, // top-left -size, -size, size, // bottom-left size, -size, size, // bottom-right // Triangle 2 size, -size, size, // bottom-right size, size, size, // top-right -size, size, size, // top-left //and then back side, left, top, right with same way ) } 

似乎逻辑,对吗? 所有的变量都有价值,NPE应该没有地方。

但是当我尝试创建Cube的实例

  val cube = Cube(this@MaterialRenderer) 

我在这一行捕获了Square类中的NullPointerException:

 private val vertexCount:Int = triangleCoords.size / COORDS_PER_VERTEX 

即使我直接分配价值

 private val vertexCount:Int = 2 

在这一行,我将在init块内的Square类中获得NPE:

 val bb = ByteBuffer.allocateDirect( triangleCoords.size * 4) 

所以我有两个问题:

1.我该如何修复它,仍然使用继承?

来自“简明英汉词典”它真的应该这样工作吗

如果你看着编辑器,它实际上警告你在构造函数中使用非final属性。 发生这种情况是因为在创建Cube ,首先需要创建一个SquareSquare创建时, Cube 不被初始化。 ( triangleCoords为null)因此, triangleCoords.size会抛出异常。

我怎样才能解决它,仍然使用继承?

你应该把它作为参数传递。

 open class Square(protected val triangleCoords: FloatArray = floatArrayOf( //first triangle -1.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, //second triangle -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f)) { val COORDS_PER_VERTEX = 3 private val vertexCount: Int = triangleCoords.size / COORDS_PER_VERTEX init { val bb = ByteBuffer.allocateDirect( triangleCoords.size * 4) //other code } } open class Cube(val size: Float = 1.0f) : Square(floatArrayOf( //front side // Triangle 1 -size, size, size, // top-left -size, -size, size, // bottom-left size, -size, size, // bottom-right // Triangle 2 size, -size, size, // bottom-right size, size, size, // top-right -size, size, size, // top-left //and then back side, left, top, right with same way )) { } 

如果你觉得这很丑,你可以编写一个工厂方法,并通过参数传递给一个私有的构造函数。

它真的应该这样工作吗?