通过实例学习java对象的构造过程-java面向对象 - it电子教育门户 高端java培训.htm

来自「这是我自己认真整理的java面向对象的各个方面的知识.想和大家一起来分享我的快乐」· HTM 代码 · 共 658 行 · 第 1/3 页

HTM
658
字号
                  ...<BR>}<BR>ChildDlg2 dlg = new ChildDlg2();&nbsp; // 
                  外部的调用<BR>你看出来两段代码之间的差别了吗?对了,两者的差别仅仅在于类变量jTextFieldName的初始化时间。经过跟踪,发现在执行panel.add(jTextFieldName)语句之时,jTextFieldName确实是空值。</FONT></P>
                  <P><FONT 
                  face="Times New Roman">我们知道,Java允许在定义类变量的同时给变量赋初始值。系统运行过程中需要创建一个对象的时候,首先会为对象分配内存空间,然后在“先于调用任何方法之前”根据变量在类内的定义顺序来初始化变量,接着再调用类的构造方法。那么,在本例中,为什么在变量定义时便初始化的代码反而会出现空指针违例呢?</FONT></P>
                  <P><FONT face="Times New Roman">对象的创建过程和初始化</FONT></P>
                  <P><FONT 
                  face="Times New Roman">实际上,前面提到的“变量初始化发生在调用任何方法包括构造方法之前”这句话是不确切的,当我们把眼光集中在单个类上时,该说法成立;然而,当把视野扩大到具有继承关系的两个或多个类上时,该说法不成立。</FONT></P>
                  <P><FONT 
                  face="Times New Roman">对象的创建一般有两种方式,一种是用new操作符,另一种是在一个Class对象上调用newInstance方法;其创建和初始化的实际过程是一样的:</FONT></P>
                  <P><FONT 
                  face="Times New Roman">首先为对象分配内存空间,包括其所有父类的可见或不可见的变量的空间,并初始化这些变量为默认值,如int类型为0,boolean类型为false,对象类型为null;</FONT></P>
                  <P><FONT face="Times New Roman">然后用下述5个步骤来初始化这个新对象:</FONT></P>
                  <P><FONT 
                  face="Times New Roman">1)分配参数给指定的构造方法;<BR>2)如果这个指定的构造方法的第一个语句是用this指针显式地调用本类的其它构造方法,则递归执行这5个步骤;如果执行过程正常则跳到步骤5;<BR>3)如果构造方法的第一个语句没有显式调用本类的其它构造方法,并且本类不是Object类(Object是所有其它类的祖先),则调用显式(用super指针)或隐式地指定的父类的构造方法,递归执行这5个步骤;如果执行过程正常则跳到步骤5;<BR>4)按照变量在类内的定义顺序来初始化本类的变量,如果执行过程正常则跳到步骤5;<BR>5)执行这个构造方法中余下的语句,如果执行过程正常则过程结束。</FONT></P>
                  <P><FONT 
                  face="Times New Roman">这一过程可以从下面的时序图中获得更清晰的认识:<BR>&nbsp;</FONT></P>
                  <P><FONT 
                  face="Times New Roman">对分析本文的实例最重要的,用一句话说,就是“父类的构造方法调用发生在子类的变量初始化之前”。可以用下面的例子来证明:</FONT></P>
                  <P><FONT face="Times New Roman">// Petstore.java<BR>class 
                  Animal {<BR>&nbsp;&nbsp;&nbsp; Animal() 
                  {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
                  System.out.println("Animal");<BR>&nbsp;&nbsp;&nbsp; 
                  }<BR>}<BR>class Cat extends Animal {<BR>&nbsp;&nbsp;&nbsp; 
                  Cat() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
                  System.out.println("Cat");<BR>&nbsp;&nbsp;&nbsp; 
                  }<BR>}<BR>class Store {<BR>&nbsp;&nbsp;&nbsp; Store() 
                  {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
                  System.out.println("Store");<BR>&nbsp;&nbsp;&nbsp; 
                  }<BR>}<BR>public class Petstore extends 
                  Store{<BR>&nbsp;&nbsp;&nbsp; Cat cat = new 
                  Cat();<BR>&nbsp;&nbsp;&nbsp; Petstore() 
                  {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
                  System.out.println("Petstore");<BR>&nbsp;&nbsp;&nbsp; 
                  }<BR>&nbsp;&nbsp;&nbsp; public static void main(String[] args) 
                  {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new 
                  Petstore();<BR>&nbsp;&nbsp;&nbsp; 
                  }<BR>}<BR>运行这段代码,它的执行结果如下:</FONT></P>
                  <P><FONT 
                  face="Times New Roman">Store<BR>Animal<BR>Cat<BR>Petstore<BR>从结果中可以看出,在创建一个Petstore类的实例时,首先调用了它的父类Store的构造方法;然后试图创建并初始化变量cat;在创建cat时,首先调用了Cat类的父类Animal的构造方法;其后才是Cat的构造方法主体,最后才是Petstore类的构造方法的主体。</FONT></P>
                  <P><FONT face="Times New Roman">寻找程序产生例外的原因</FONT></P>
                  <P><FONT 
                  face="Times New Roman">现在回到本文开始提到的实例中来,当程序创建一个ChildDlg2的实例时,根据super(null, 
                  “Title”)语句,首先执行其父类BaseDlg的构造方法;在BaseDlg的构造方法中调用了createClientPanel()方法,这个方法是抽象方法并且被子类ChildDlg2实现了,因此,实际调用的方法是ChildDlg2中的createClientPanel()方法(因为Java里面采用“动态绑定”来绑定所有非final的方法);createClientPanel()方法使用了ChildDlg2类的实例变量jTextFieldName,而此时ChildDlg2的变量初始化过程尚未进行,jTextFieldName是null值!所以,ChildDlg2的构造过程掷出一个NullPointerException也就不足为奇了。</FONT></P>
                  <P><FONT 
                  face="Times New Roman">再来看ChildDlg1,它的jTextFieldName的初始化代码写在了createClientPanel()方法内部的开始处,这样它就能保证在使用之前得到正确的初始化,因此这段代码工作正常。</FONT></P>
                  <P><FONT face="Times New Roman">解决问题的两种方式</FONT></P>
                  <P><FONT 
                  face="Times New Roman">通过上面的分析过程可以看出,要排除故障,最简单的方法就是要求项目组成员在继承使用BaseDlg类,实现createClientPanel()方法时,凡方法内部要使用的变量必须首先正确初始化,就象ChildDlg1一样。然而,把类变量放在类方法内初始化是一种很不好的设计行为,它最适合的地方就是在变量定义块和构造方法中。</FONT></P>
                  <P><FONT 
                  face="Times New Roman">在本文的实例中,引发错误的实质并不在ChildDlg2上,而在其父类BaseDlg上,是它在自己的构造方法中不适当地调用了一个待实现的抽象方法。</FONT></P>
                  <P><FONT 
                  face="Times New Roman">从概念上讲,构造方法的职责是正确初始化类变量,让对象进入可用状态。而BaseDlg却赋给了构造方法额外的职责。</FONT></P>
                  <P><FONT 
                  face="Times New Roman">本文实例的更好的解决方法是修改BaseDlg类:</FONT></P>
                  <P><FONT face="Times New Roman">public abstract class BaseDlg 
                  extends JDialog {<BR>&nbsp;&nbsp;&nbsp; public BaseDlg(Frame 
                  frame, String title) 
                  {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(frame, 
                  title, true);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
                  this.getContentPane().setLayout(new 
                  BorderLayout());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
                  this.getContentPane().add(createHeadPanel(), 
                  BorderLayout.NORTH);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
                  this.getContentPane().add(createButtonPanel(), 
                  BorderLayout.SOUTH);<BR>&nbsp;&nbsp;&nbsp; }</FONT></P>
                  <P><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp; /** 
                  创建对话框实例后,必须调用此方法来布局用户界面<BR>&nbsp;&nbsp;&nbsp;&nbsp; 
                  */<BR>&nbsp;&nbsp;&nbsp; public void initGUI() 
                  {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
                  this.getContentPane().add(createClientPanel(), 
                  BorderLayout.CENTER);<BR>&nbsp;&nbsp;&nbsp; }</FONT></P>
                  <P><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp; private 
                  JPanel createHeadPanel() 
                  {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ... // 
                  创建对话框头部<BR>&nbsp;&nbsp;&nbsp; }</FONT></P>
                  <P><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp; // 
                  创建对话框客户区域,交给子类实现<BR>&nbsp;&nbsp;&nbsp; protected abstract 
                  JPanel createClientPanel();</FONT></P>
                  <P><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp; private 
                  JPanel createButtonPanel 
                  {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ... // 
                  创建按钮区域<BR>&nbsp;&nbsp;&nbsp; 
                  }<BR>}<BR>新的BaseDlg类增加了一个initGUI()方法,程序员可以这样使用这个类:</FONT></P>
                  <P><FONT face="Times New Roman">ChildDlg dlg = new 
                  ChildDlg();<BR>dlg.initGUI();<BR>dlg.setVisible(true);<BR>总结</FONT></P>
                  <P><FONT 
                  face="Times New Roman">类的构造方法的基本目的是正确初始化类变量,不要赋予它过多的职责。</FONT></P>
                  <P><FONT 
                  face="Times New Roman">设计类构造方法的基本规则是:用尽可能简单的方法使对象进入就绪状态;如果可能,避免调用任何方法。在构造方法内唯一能安全调用的是基类中具有final属性的方法或者private方法(private方法会被编译器自动设置final属性)。final的方法因为不能被子类覆盖,所以不会产生问题。</FONT></P></DIV></SPAN></TD></TR>
              <TR>
                <TD width="71%">&nbsp;</TD>
                <TD width="29%">【 <A 
                  href="http://www.mldn.cn/print.jtml?articleid=2618">打印</A> 】【 
                  <A 
                  href="http://www.mldn.cn/member/favlist.jtml?action=add&amp;postid=2618">收藏</A> 
                  】【 <A href="http://www.mldn.cn/email.jtml?articleid=2618" 
                  target=_blank>推荐</A> 】&nbsp;</TD></TR>
              <TR>
                <TD colSpan=2>
                  <TABLE cellSpacing=3 cellPadding=0 width="100%" align=center 
                  bgColor=#ffffff border=0>
                    <TBODY>
                    <TR height=25>
                      <TD align=middle width="33%"><IMG height=95 alt=java视频教程 
                        src="通过实例学习Java对象的构造过程-JAVA面向对象 - IT电子教育门户 高端JAVA培训.files/javavideo.gif" 
                        width=642></TD></TR>
                    <TR>
                      <TD class=content-table vAlign=top align=middle>
                        <TABLE>
                          <TBODY>
                          <TR>
                            <TD>
                              <TABLE>
                                <TBODY>
                                <TR>
                                <TD><A 
                                href="http://www.mldn.cn/articleview/2007-8-21/article_view_2251.htm" 
                                rel=external><IMG class=midImg alt=struts2.0入门视频 
                                src="通过实例学习Java对象的构造过程-JAVA面向对象 - IT电子教育门户 高端JAVA培训.files/struts2.gif" 
                                width=90></A></TD></TR>
                                <TR>
                                <TD style="HEIGHT: 22px">&nbsp;<A 
                                title=struts2.0入门视频 
                                href="http://www.mldn.cn/articleview/2007-8-21/article_view_2251.htm" 
                                rel=external>struts2.0入门视频</A></TD></TR></TBODY></TABLE></TD>
                            <TD>
                              <TABLE>
                                <TBODY>
                                <TR>
                                <TD><A 
                                href="http://www.mldn.cn/articleview/2007-6-15/article_view_2141.htm" 
                                rel=external><IMG class=midImg 
                                alt=JAVAEE学习流程和学习方法 
                                src="通过实例学习Java对象的构造过程-JAVA面向对象 - IT电子教育门户 高端JAVA培训.files/j2eejc.gif" 
                                width=90></A></TD></TR>
                                <TR>
                                <TD style="HEIGHT: 22px">&nbsp;<A 
                                title=JAVAEE学习流程和学习方法 
                                href="http://www.mldn.cn/articleview/2007-6-15/article_view_2141.htm" 
                                rel=external>JAVAEE学习流程和学习方..</A></TD></TR></TBODY></TABLE></TD>
                            <TD>
                              <TABLE>
                                <TBODY>
                                <TR>
                                <TD><A 
                                href="http://www.mldn.cn/articleview/2007-6-5/article_view_2091.htm" 
                                rel=external><IMG class=midImg 
                                alt=1-Java介绍及JDK配置 
                                src="通过实例学习Java对象的构造过程-JAVA面向对象 - IT电子教育门户 高端JAVA培训.files/javase.gif" 
                                width=90></A></TD></TR>
                                <TR>
                                <TD style="HEIGHT: 22px">&nbsp;<A 
                                title=1-Java介绍及JDK配置 
                                href="http://www.mldn.cn/articleview/2007-6-5/article_view_2091.htm" 
                                rel=external>1-Java介绍及JDK配置..</A></TD></TR></TBODY></TABLE></TD>
                            <TD>
                              <TABLE>
                                <TBODY>
                                <TR>
                                <TD><A 
                                href="http://www.mldn.cn/articleview/2007-4-19/article_view_2012.htm" 
                                rel=external><IMG class=midImg alt=Oracle中的多表连接 
                                src="通过实例学习Java对象的构造过程-JAVA面向对象 - IT电子教育门户 高端JAVA培训.files/Oracle.gif" 
                                width=90></A></TD></TR>
                                <TR>
                                <TD style="HEIGHT: 22px">&nbsp;<A 
                                title=Oracle中的多表连接 
                                href="http://www.mldn.cn/articleview/2007-4-19/article_view_2012.htm" 
                                rel=external>Oracle中的多表连接</A></TD></TR></TBODY></TABLE></TD>
                            <TD>
                              <TABLE>
                                <TBODY>
                                <TR>
                                <TD><A 
                                href="http://www.mldn.cn/articleview/2007-4-11/article_view_1978.htm" 
                                rel=external><IMG class=midImg 
                                alt=Struts中logic标签的使用 
                                src="通过实例学习Java对象的构造过程-JAVA面向对象 - IT电子教育门户 高端JAVA培训.files/struts.gif" 
                                width=90></A></TD></TR>
                                <TR>
                                <TD style="HEIGHT: 22px">&nbsp;<A 
                                title=Struts中logic标签的使用 
                                href="http://www.mldn.cn/articleview/2007-4-11/article_view_1978.htm" 
                                rel=external>Struts中logic标签..</A></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></TD></TR>
              <TR>
                <TD colSpan=2>
                  <TABLE cellSpacing=3 cellPadding=0 width="100%" align=center 
                  bgColor=#ffffff border=0>
                    <TBODY>
                    <TR height=25>
                      <TD align=middle width="33%" bgColor=#aac4c4><FONT 
                        color=#ffffff>相关文章</FONT></TD>
                      <TD align=middle width="33%" bgColor=#aac4c4><FONT 
                        color=#ffffff>推荐文章</FONT></TD></TR>
                    <TR>
                      <TD class=content-table vAlign=top>
                        <TABLE>
                          <TBODY>
                          <TR>
                            <TD><A 
                              href="http://www.mldn.cn/articleview/2007-11-7/article_view_2650.htm" 
                              rel=external>垃圾收集器与Java程序的性能</A>&nbsp;<IMG 
                              alt=24小时内新文章 
                              src="通过实例学习Java对象的构造过程-JAVA面向对象 - IT电子教育门户 高端JAVA培训.files/new.gif" 
                              align=absMiddle border=0></TD>
                            <TD style="TEXT-ALIGN: right"><SPAN 
                              class=link-Date>[11.7]</SPAN></TD></TR>
                          <TR>
                            <TD><A 
                              href="http://www.mldn.cn/articleview/2007-11-7/article_view_2652.htm" 
                              rel=external>详细解析Java中抽象类和接口的..</A>&nbsp;<IMG 
                              alt=24小时内新文章 
                              src="通过实例学习Java对象的构造过程-JAVA面向对象 - IT电子教育门户 高端JAVA培训.files/new.gif" 
                              align=absMiddle border=0></TD>
                            <TD style="TEXT-ALIGN: right"><SPAN 
                              class=link-Date>[11.7]</SPAN></TD></TR>
                          <TR>
                            <TD><A 
                              href="http://www.mldn.cn/articleview/2007-11-2/article_view_2624.htm" 
                              rel=external>讲述java语言中内部类的研究</A></TD>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?