我知道從構造函數中調用可重寫的方法是一個壞主意。但我也看到它在Swing中隨處可見,其中代碼如add(new JLabel("Something"));
一直在構造函數中出現。例如,以NetBeans IDE爲例。對構造函數中的可重複調用非常挑剔。然而,當它生成Swing代碼時,它會將所有這些方法調用放入initializeComponents()
方法中,然後從構造函數中調用它!一種隱藏問題並禁用警告的好方法(NetBeans沒有「調用可覆蓋方法的私有方法從構造函數中調用」警告)。但不是真正的解決問題的方法。調用可重寫的方法,如Swing的add()在構造函數中
這是怎麼回事?我已經做了很多年,但總是對此感到不安。有沒有更好的初始化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
}
}
}
它可以保持代碼更清潔,但它不會使*更安全*。相反,問題現在隱藏了,但它仍然存在。即使init函數是私有的,它調用的函數,如add(),也不是。所以如果有人推翻add(),你會遇到完全相同的問題,只能隱藏在私有函數中!這是我的問題的重點。 –
請參閱我的編輯例如。 –