Java类初始化难题
我使用 NetBeans 的 GUI 设计器创建一些 JDialog
,然后从我自己的 EditorDialog
类中继承它们。
在进一步讨论之前,请考虑以下示例代码:
class MyDialog extends EditorDialog {
private Color someVariableThatTheGuiNeeds = new Color(0,50,100);
public MyDialog() {
super(true);
}
//<auto-generated>
private void initComponents() { //note this is private!
//...
}
//</auto-generated>
}
abstract class EditorDialog extends JDialog {
public EditorDialog() {
super(null,true);
}
public EditorDialog(boolean stuffNeedsDone) {
super(null,true);
//initComponents();
doStuffAfterGuiInitialized();
}
}
问题是,我无法从我的超类中调用 initComponents()
,因为它是私有的。
为了解决这个问题,我尝试了对类的解决方法:
//in EditorDialog
public EditorDialog(boolean stuffNeedsDone) {
super(null,true);
workaround();
doStuffAfterGuiInitialized();
}
protected abstract void workaround();
//in MyDialog
@Override
protected void workaround() {
initComponents();
}
当然,这不起作用,因为调用 initComponents()
时 someVariableThatTheGuiNeeds
未初始化由于初始化发生的方式:
new MyDialog()
超级(这个)
EditorDialog(boolean)
被调用super(null,true)
被调用,JDialog
执行操作EditorDialog
的实例变量已初始化解决方法()
initComponents()
doSomethingWith(someVariableThatTheGuiNeeds)
-> NullPointerException 因为someVariableThatTheGuiNeeds
尚未初始化
- 现在
someVariableThatTheGuiNeeds
已初始化
另外,我无法创建非私有抽象EditorDialog
中的 initComponents()
,因为覆盖时的可见性只能变得更加公开。
那么,我怎样才能解决这个问题,而又不会让它变得太黑客化呢?
(如果您不熟悉 NetBeans,我无法编辑自动生成的代码,并且没有(我能找到的)选项来更改 initComponents()
上的访问修饰符方法。
I am using NetBeans' GUI Designer to create some JDialog
s, which I then subclass from my own EditorDialog
class.
Before I go further, consider this sample code:
class MyDialog extends EditorDialog {
private Color someVariableThatTheGuiNeeds = new Color(0,50,100);
public MyDialog() {
super(true);
}
//<auto-generated>
private void initComponents() { //note this is private!
//...
}
//</auto-generated>
}
abstract class EditorDialog extends JDialog {
public EditorDialog() {
super(null,true);
}
public EditorDialog(boolean stuffNeedsDone) {
super(null,true);
//initComponents();
doStuffAfterGuiInitialized();
}
}
The problem is, I can't call initComponents()
from my superclass, because it is private.
To get around this, I tried a workaround to the classes:
//in EditorDialog
public EditorDialog(boolean stuffNeedsDone) {
super(null,true);
workaround();
doStuffAfterGuiInitialized();
}
protected abstract void workaround();
//in MyDialog
@Override
protected void workaround() {
initComponents();
}
And, of course, this doesn't work, because someVariableThatTheGuiNeeds
isn't initialized when initComponents()
gets called because of the way the initializations happen:
new MyDialog()
super(this)
EditorDialog(boolean)
is calledsuper(null,true)
is called,JDialog
does stuffEditorDialog
's instance variables are initializedworkaround()
initComponents()
doSomethingWith(someVariableThatTheGuiNeeds)
-> NullPointerException becausesomeVariableThatTheGuiNeeds
isn't initialized yet
- NOW
someVariableThatTheGuiNeeds
is initialized
Also, I cannot create a non-private abstract initComponents()
in EditorDialog
, because the visibility when overriding can only become more public.
So, how can I get around this problem, without making it too hackish?
(If you are unfamiliar with NetBeans, I cannot edit auto-generated code, and there is no option (that I could find) to change access modifiers on the initComponents()
method.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在任何情况下,您的构造函数都不应该调用非
私有
方法。如果您需要在创建对话框后对其进行初始化,则可以创建一个init()
方法,该方法应在构造函数完成后调用。请注意,方法名称
doStuffAfterGuiInitialized()
表示有点误解。 GUI,甚至实例,直到构造函数完成之后才完全初始化。Your constructors shouldn't call non-
private
methods in any case. If you require initialization for your dialogs after they are created, you can create aninit()
method that should be called after the constructor is finished.Note, the method name
doStuffAfterGuiInitialized()
indicates a bit of a misunderstanding. The GUI, or even the instance, isnt fully initialized until after the constructor completes.这是java中常见的问题。
实例化不是子类化的朋友。
许多人使用间接解决方案:在对象完全构建后调用 init() 方法。
这通常是通过工厂实现自动化的。
所有注入框架(如 Spring)都会例行执行此操作。
This is a problem that is common in java.
Instanciation is not a friend of subclassing.
An indirect solution is used by many : call an init() method once the object is fully build.
This is often automated via a factory.
All injection frameworks (like Spring) do this routinely.