Переменная экземпляра, инициализированная в конструкторе класса, становится недействительной в переопределенном методе
Здесь у меня есть простой класс, который расширяет класс в графической библиотеке ACM под названием GRect. Grect - это основной прямоугольник, который можно нарисовать в GCanvas (также является частью ACM). Чего я хочу добиться, так это нового объекта, который представляет собой прямоугольник, но имеет прикрепленную метку, которая перемещается вместе с прямоугольником.
В моем коде я создал класс с именем labeledRect, который расширяет GRect и содержит переменную экземпляра "rectLabel", имеющую тип GLabel, которая инициализируется в конструкторе labeledRects. Я хочу переопределить некоторые из методов GRect, чтобы при перемещении labledRect с ним перемещался rectLabel.
Моя проблема заключается в том, что несмотря на то, что "rectLabel" объявляется как переменная экземпляра и инициализируется в конструкторе, он становится NULL в переопределенном методе "setLocation". Я также попытался инициализировать "rectLabel" при объявлении, но возникает та же проблема.
import acm.graphics.*;
public class labeledRect extends GRect {
//GLabel declared as an instance variable
public GLabel rectLabel;
public labeledRect(double x, double y, double width, double height, String theLabel) {
//Call GRect constructor
super(x, y, width, height);
//Label initialized.
//Location setting and adding to the canvas works fine here.
rectLabel = new GLabel(theLabel);
rectLabel.setLocation(
x + (width / 2) - (rectLabel.getWidth() / 2),
y + (height / 2) + (rectLabel.getAscent() / 2.2));
}
public void setLocation(double x, double y)
{
//Setting GRect's location. Works correctly./
super.setLocation(x, y);
//Attempt to set the label's location
//and get a NullPointer exception for rectLabel
rectLabel.setLocation(
super.getX() - (rectLabel.getWidth() / 2),
super.getY() - (rectLabel.getHeight() / 2));
}
}
1 ответ
Трудно рассуждать о том, что именно может устанавливать переменную в null, учитывая, что это открытое поле. Это первое, что вы должны изменить. Поля почти всегда должны быть приватными.
Далее вы говорите setLocation
это переопределенный метод - он вызывается в GRect
конструктор случайно? Если так, это будет вызвано до того, как значение будет установлено в пределах labeledRect
конструктор, который вполне может быть причиной вашей проблемы.
В Java конструктор суперкласса выполняется перед любым кодом в подклассе - как перед инициализаторами переменных экземпляра, так и перед телом конструктора. Все переменные будут иметь свои значения по умолчанию. Вот почему плохая идея вызывать виртуальные методы из конструкторов.
(В сторону, название labeledRect
не следует соглашениям об именах Java.)