Я знаю, что вызов переопределяемых методов из конструкторов - плохая идея. Но я также вижу, что это происходит везде с Swing, где код типа add(new JLabel("Something"));
встречается в конструкторах все время.
Возьмите NetBeans IDE, например. Это очень разборчиво по поводу сложных вызовов в конструкторах. И все же, когда он генерирует код Swing, он помещает все эти вызовы метода add()
в метод initializeComponents()
... который затем вызывается из конструктора! Хороший способ скрыть проблему и отключить предупреждение (NetBeans не имеет "частного метода, который вызывает переопределяемые методы, вызывается из предупреждения конструктора" ). Но на самом деле это не способ решить проблему.
Что здесь происходит? Я делал это целую вечность, но всегда испытывал неловкое чувство об этом. Есть ли лучший способ инициализации контейнеров Swing, за исключением создания дополнительного метода init()
(и не забудьте вызвать его каждый раз, что является скучным)?
Пример
Вот очень надуманный пример того, как все может пойти не так:
public class MyBasePanel extends JPanel {
public MyBasePanel() {
initializeComponents();
}
private void initializeComponents() {
// layout setup omitted
// overridable call
add(new JLabel("My label"), BorderLayout.CENTER);
}
}
public class MyDerivedPanel extends MyBasePanel {
private final List<JLabel> addedLabels = new ArrayList<>();
@Override
public void add(Component comp, Object constraints) {
super.add(comp);
if (comp instanceof JLabel) {
JLabel label = (JLabel) comp;
addedLabels.add(label); // NPE here
}
}
}