熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> JSP教程 >> 正文

構建器內部的多形性方法的行為

2013-11-15 11:50:31  來源: JSP教程 

  構建器調用的分級結構(順序)為我們帶來了一個有趣的問題或者說讓我們進入了一種進退兩難的局面若當前位於一個構建器的內部同時調用准備構建的那個對象的一個動態綁定方法那麼會出現什麼情況呢?在原始的方法內部我們完全可以想象會發生什麼——動態綁定的調用會在運行期間進行解析因為對象不知道它到底從屬於方法所在的那個類還是從屬於從它衍生出來的某些類為保持一致性大家也許會認為這應該在構建器內部發生
  
  但實際情況並非完全如此若調用構建器內部一個動態綁定的方法會使用那個方法被覆蓋的定義然而產生的效果可能並不如我們所願而且可能造成一些難於發現的程序錯誤
  
  從概念上講構建器的職責是讓對象實際進入存在狀態在任何構建器內部整個對象可能只是得到部分組織——我們只知道基礎類對象已得到初始化但卻不知道哪些類已經繼承然而一個動態綁定的方法調用卻會在分級結構裡向前或者向外前進它調用位於衍生類裡的一個方法如果在構建器內部做這件事情那麼對於調用的方法它要操縱的成員可能尚未得到正確的初始化——這顯然不是我們所希望的
  
  通過觀察下面這個例子這個問題便會昭然若揭
  
  //: PolyConstructorsjava
  // Constructors and polymorphism
  // dont produce what you might expect
  
  abstract class Glyph {
   abstract void draw();
   Glyph() {
    Systemoutprintln(Glyph() before draw());
    draw();
    Systemoutprintln(Glyph() after draw());
   }
  }
  
  class RoundGlyph extends Glyph {
   int radius = ;
   RoundGlyph(int r) {
    radius = r;
    Systemoutprintln(
     RoundGlyphRoundGlyph() radius =
     + radius);
   }
   void draw() {
    Systemoutprintln(
     RoundGlyphdraw() radius = + radius);
   }
  }
  
  public class PolyConstructors {
   public static void main(String[] args) {
    new RoundGlyph();
   }
  } ///:~
  
  在Glyph中draw()方法是抽象的(abstract)所以它可以被其他方法覆蓋事實上我們在RoundGlyph中不得不對其進行覆蓋但Glyph構建器會調用這個方法而且調用會在RoundGlyphdraw()中止這看起來似乎是有意的但請看看輸出結果
  
  Glyph() before draw()
  RoundGlyphdraw() radius =
  Glyph() after draw()
  RoundGlyphRoundGlyph() radius =
  
  當Glyph的構建器調用draw()時radius的值甚至不是默認的初始值而是這可能是由於一個點號或者屏幕上根本什麼都沒有畫而造成的這樣就不得不開始查找程序中的錯誤試著找出程序不能工作的原因
  
  前一節講述的初始化順序並不十分完整而那是解決問題的關鍵所在初始化的實際過程是這樣的
  
  () 在采取其他任何操作之前為對象分配的存儲空間初始化成二進制零
  
  () 就象前面敘述的那樣調用基礎類構建器此時被覆蓋的draw()方法會得到調用(的確是在RoundGlyph構建器調用之前)此時會發現radius的值為這是由於步驟()造成的
  
  () 按照原先聲明的順序調用成員初始化代碼
  
  () 調用衍生類構建器的主體
  
  采取這些操作要求有一個前提那就是所有東西都至少要初始化成零(或者某些特殊數據類型與等價的值)而不是僅僅留作垃圾其中包括通過合成技術嵌入一個類內部的對象句柄如果假若忘記初始化那個句柄就會在運行期間出現違例事件其他所有東西都會變成零這在觀看結果時通常是一個嚴重的警告信號
  
  在另一方面應對這個程序的結果提高警惕從邏輯的角度說我們似乎已進行了無懈可擊的設計所以它的錯誤行為令人非常不可思議而且沒有從編譯器那裡收到任何報錯信息(C++在這種情況下會表現出更合理的行為)象這樣的錯誤會很輕易地被人忽略而且要花很長的時間才能找出
  
  因此設計構建器時一個特別有效的規則是用盡可能簡單的方法使對象進入就緒狀態如果可能避免調用任何方法在構建器內唯一能夠安全調用的是在基礎類中具有final屬性的那些方法(也適用於private方法它們自動具有final屬性)這些方法不能被覆蓋所以不會出現上述潛在的問題
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19731.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.