<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    BlueIce  
    藍色的Java,冰色的BillQian
    日歷
    <2007年7月>
    24252627282930
    1234567
    891011121314
    15161718192021
    22232425262728
    2930311234
    統(tǒng)計
    • 隨筆 - 5
    • 文章 - 0
    • 評論 - 5
    • 引用 - 0

    導航

    常用鏈接

    留言簿(2)

    隨筆檔案

    相冊

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

     
      今天在網上看到一篇文章,感覺很好,它講到的是關于構造函數的作用以及類的構造問題,而這是初學者經常會犯甚至是有經驗的程序員偶爾也會犯的錯誤,在此我舉例總結一下,請看下面這段代碼:
      
    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()?{
    ?????????
    //?創(chuàng)建對話框頭部
    ????}


    ????
    //?創(chuàng)建對話框客戶區(qū)域,交給子類實現
    ????protected?abstract?JPanel?createClientPanel();

    ????
    private?JPanel?createButtonPanel?{
    ?????????
    //?創(chuàng)建按鈕區(qū)域
    ????}

    }


      這個類在有的代碼中工作得很好,但一個同事在使用時,程序卻擲出了一個NullPointerException違例!經過比較,找出了工作正常和不正常的程序的細微差別,代碼片斷分別如下:
      一、工作正常的代碼:
            
    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();??//?外部的調用
     
      二、工作不正常的代碼:
          
    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的初始化時間。經過跟蹤,發(fā)現在執(zhí)行
    panel.add(jTextFieldName)語句之時,jTextFieldName確實是空值.

      當程序創(chuàng)建一個ChildDlg2的實例時,根據super(null,?“Title”)語句,首先執(zhí)行其父類BaseDlg的構造方法;在BaseDlg的構造方法中調用了createClientPanel()方法,這個方法是抽象方法并且被子類ChildDlg2實現了,因此,實際調用的方法是ChildDlg2中的createClientPanel()方法(因為Java里面采用“動態(tài)綁定”來綁定所有非final的方法);createClientPanel()方法使用了ChildDlg2類的實例變量jTextFieldName,而此時ChildDlg2的變量初始化過程尚未進行,jTextFieldName是null值!所以,ChildDlg2的構造過程擲出一個NullPointerException也就不足為奇了。

      再來看ChildDlg1,它的jTextFieldName的初始化代碼寫在了createClientPanel()方法內部的開始處,這樣它就能保證在使用之前得到正確的初始化,因此這段代碼工作正常。

    解決問題的兩種方式:

      通過上面的分析過程可以看出,要排除故障,最簡單的方法就是要求項目組成員在繼承使用BaseDlg類,實現createClientPanel()方法時,凡方法內部要使用的變量必須首先正確初始化,就象ChildDlg1一樣。然而,把類變量放在類方法內初始化是一種很不好的設計行為,它最適合的地方就是在變量定義塊和構造方法中。

      在本文的實例中,引發(fā)錯誤的實質并不在ChildDlg2上,而在其父類BaseDlg上,是它在自己的構造方法中不適當地調用了一個待實現的抽象方法。

    從概念上講,構造方法的職責是正確初始化類變量,讓對象進入可用狀態(tài)。而BaseDlg卻賦給了構造方法額外的職責。

    本文實例的更好的解決方法是修改BaseDlg類:
      
    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(createButtonPanel(),?BorderLayout.SOUTH);
    ????}


    ????
    /**?創(chuàng)建對話框實例后,必須調用此方法來布局用戶界面
    ?????
    */

    ????
    public?void?initGUI()?{
    ????????
    this.getContentPane().add(createClientPanel(),?BorderLayout.CENTER);
    ????}


    ????
    private?JPanel?createHeadPanel()?{
    ?????????
    //?創(chuàng)建對話框頭部
    ????}


    ????
    //?創(chuàng)建對話框客戶區(qū)域,交給子類實現
    ????protected?abstract?JPanel?createClientPanel();

    ????
    private?JPanel?createButtonPanel?{
    ?????????
    //?創(chuàng)建按鈕區(qū)域
    ????}

    }


    新的BaseDlg類增加了一個initGUI()方法,程序員可以這樣使用這個類:

    ChildDlg?dlg?=?new?ChildDlg();
    dlg.initGUI();
    dlg.setVisible(
    true);

    總結:

      類的構造方法的基本目的是正確初始化類變量,不要賦予它過多的職責。

      設計類構造方法的基本規(guī)則是:用盡可能簡單的方法使對象進入就緒狀態(tài);如果可能,避免調用任何方法。在構造方法內唯一能安全調用的是基類中具有final屬性的方法或者private方法(private方法會被編譯器自動設置final屬性)。final的方法因為不能被子類覆蓋,所以不會產生問題。
    posted on 2007-03-02 12:58 BillQian 閱讀(367) 評論(3)  編輯  收藏
    評論:
    • # re: 詭秘的Java構造問題...  uTsing Posted @ 2007-03-02 13:09
      不錯不錯~
      希望繼續(xù)努力~  回復  更多評論   

    • # re: 詭秘的Java構造問題...  qiuxin1337 Posted @ 2007-03-03 15:50
      挺好的!就是我看不太懂,呵呵!
      好好做吧同志!A ZA!  回復  更多評論   

    • # re: 詭秘的Java構造問題...  itkui Posted @ 2007-07-03 14:32
      雖然現在都學習struts、hibernate了。
      可是,Java語言本身理解的還是不透徹。
      哎,只有繼續(xù)了。。。  回復  更多評論   


    只有注冊用戶登錄后才能發(fā)表評論。


    網站導航:
     
     
    Copyright © BillQian Powered by: 博客園 模板提供:滬江博客
    主站蜘蛛池模板: 18禁黄网站禁片免费观看不卡| a级毛片免费高清视频| 国产成人免费ā片在线观看老同学| 国产网站免费观看| 亚洲精品V天堂中文字幕| 成人在线免费观看| 亚洲国产成人综合精品| 日本a级片免费看| 无人视频免费观看免费视频| 免费a级毛片大学生免费观看 | 国产精品玖玖美女张开腿让男人桶爽免费看| 在线永久免费观看黄网站| 老司机亚洲精品影院在线观看| 在线免费观看色片| 美景之屋4在线未删减免费 | 久久精品国产亚洲一区二区三区 | 456亚洲人成影院在线观| 日本免费网址大全在线观看| 亚洲一级毛片免费在线观看| 日本人护士免费xxxx视频| 美景之屋4在线未删减免费| 亚洲婷婷五月综合狠狠爱| 无码日韩精品一区二区免费暖暖| 亚洲第一香蕉视频| 麻豆国产人免费人成免费视频| 狠狠热精品免费观看| 亚洲精品亚洲人成人网| av无码免费一区二区三区| 蜜芽亚洲av无码一区二区三区| 久久亚洲精品无码观看不卡| 日本免费一区二区三区| 亚洲欧美日韩中文字幕一区二区三区| 亚洲福利在线播放| 182tv免费观看在线视频| 亚洲精华国产精华精华液| 亚洲人成色777777在线观看| 黄色网址免费大全| 4hu四虎免费影院www| 亚洲成a人片毛片在线| 五月婷婷亚洲综合| 国产精品怡红院永久免费|