分类:
2008-09-09 15:16:58
public abstract class BaseDlg extends JDialog { public BaseDlg(Frame frame, String title) { super(frame, title, true); this.getContentPane().setLayout(new BorderLayout()); this.getContentPane().add(createHeadPanel(), BorderLayout.NORTH); this.getContentPane().add(createClientPanel(), BorderLayout.CENTER); this.getContentPane().add(createButtonPanel(), BorderLayout.SOUTH); } private JPanel createHeadPanel() { ... // 创建对话框头部 } // 创建对话框客户区域,交给子类实现 protected abstract JPanel createClientPanel(); private JPanel createButtonPanel { ... // 创建按钮区域 } } |
public class ChildDlg1 extends BaseDlg { JTextField jTextFieldName; public ChildDlg1() { super(null, "Title"); } public JPanel createClientPanel() { jTextFieldName = new JTextField(); JPanel panel = new JPanel(new FlowLayout()); panel.add(jTextFieldName); ... // 其它代码 return panel; } ... } ChildDlg1 dlg = new ChildDlg1(frame, "Title"); // 外部的调用 |
public class ChildDlg2 extends BaseDlg { JTextField jTextFieldName = new JTextField(); public ChildDlg2() { super(null, "Title"); } public JPanel createClientPanel() { JPanel panel = new JPanel(new FlowLayout()); panel.add(jTextFieldName); ... // 其它代码 return panel; } ... } ChildDlg2 dlg = new ChildDlg2(); // 外部的调用 |
你看出来两段代码之间的差别了吗?对了,两者的差别仅仅在于类变量jTextFieldName的初始化时间。经过跟踪,发现在执行panel.add(jTextFieldName)语句之时,jTextFieldName确实是空值。
我们知道,Java允许在定义类变量的同时给变量赋初始值。系统运行过程中需要创建一个对象的时候,首先会为对象分配内存空间,然后在“先于调用任何方法之前”根据变量在类内的定义顺序来初始化变量,接着再调用类的构造方法。那么,在本例中,为什么在变量定义时便初始化的代码反而会出现空指针违例呢?
对象的创建过程和初始化
实际上,前面提到的“变量初始化发生在调用任何方法包括构造方法之前”这句话是不确切的,当我们把眼光集中在单个类上时,该说法成立;然而,当把视野扩大到具有继承关系的两个或多个类上时,该说法不成立。
对象的创建一般有两种方式,一种是用new操作符,另一种是在一个Class对象上调用newInstance方法;其创建和初始化的实际过程是一样的:
首先为对象分配内存空间,包括其所有父类的可见或不可见的变量的空间,并初始化这些变量为默认值,如int类型为0,boolean类型为false,对象类型为null;
然后用下述5个步骤来初始化这个新对象:
1)分配参数给指定的构造方法;
2)如果这个指定的构造方法的第一个语句是用this指针显式地调用本类的其它构造方法,则递归执行这5个步骤;如果执行过程正常则跳到步骤5;
3)如果构造方法的第一个语句没有显式调用本类的其它构造方法,并且本类不是Object类(Object是所有其它类的祖先),则调用显式(用super指针)或隐式地指定的父类的构造方法,递归执行这5个步骤;如果执行过程正常则跳到步骤5;
4)按照变量在类内的定义顺序来初始化本类的变量,如果执行过程正常则跳到步骤5;
5)执行这个构造方法中余下的语句,如果执行过程正常则过程结束。
这一过程可以从下面的时序图中获得更清晰的认识:
[1]