Ser*_*nov 23 java swing constructor overriding
我知道从构造函数中调用可覆盖的方法是个坏主意.但我也看到它在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
}
}
}
Run Code Online (Sandbox Code Playgroud)
为避免在构造函数中将Swing组件连接在一起,您可以简单地将布线的责任交给另一个对象.例如,您可以向工厂提供接线任务:
public class MyPanelFactory {
public MyBasePanel myBasePanel() {
MyBasePanel myBasePanel = new MyBasePanel();
initMyBasePanel(myBasePanel);
return myBasePanel;
}
public MyDerivedPanel myDerivedPanel() {
MyDerivedPanel myDerivedPanel = new MyDerivedPanel();
initMyBasePanel(myDerivedPanel);
return myDerivedPanel;
}
private void initMyBasePanel(MyBasePanel myBasePanel) {
myBasePanel.add(new JLabel("My label"), BorderLayout.CENTER);
}
}
Run Code Online (Sandbox Code Playgroud)
或者您可以全力以赴,使用依赖注入容器实例化所有Swing组件,并让容器触发连线.这是Dagger的一个例子:
@Module
public class MyPanelModule {
static class MyBasePanel extends JPanel {
private final JLabel myLabel;
MyBasePanel(JLabel myLabel) {
this.myLabel = myLabel;
}
void initComponents() {
this.add(myLabel, BorderLayout.CENTER);
}
}
static class MyDerivedPanel extends MyBasePanel {
private final List<JLabel> addedLabels = new ArrayList<>();
MyDerivedPanel(JLabel myLabel) {
super(myLabel);
}
@Override
public void add(Component comp, Object constraints) {
super.add(comp);
if (comp instanceof JLabel) {
JLabel label = (JLabel) comp;
addedLabels.add(label);
}
}
}
@Provides MyBasePanel myBasePanel(@Named("myLabel") JLabel myLabel) {
MyBasePanel myBasePanel = new MyBasePanel(myLabel);
myBasePanel.initComponents();
return myBasePanel;
}
@Provides MyDerivedPanel myDerivedPanel(@Named("myLabel") JLabel myLabel) {
MyDerivedPanel myDerivedPanel = new MyDerivedPanel(myLabel);
myDerivedPanel.initComponents();
return myDerivedPanel;
}
@Provides @Named("myLabel") JLabel myLabel() {
return new JLabel("My label");
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
536 次 |
| 最近记录: |