1. 程式人生 > >關於父類和子類的初始化問題

關於父類和子類的初始化問題

在Java中建立一個類的物件時,如果該類存在父類,則先呼叫父類的構造方法,然後再呼叫子類的構造方法。如果父類沒有定義構造方法,則呼叫編譯器自動建立的不帶引數的預設構造方法。如果父類定義了public的無參的構造方法,則在呼叫子類的構造方法前會自動先呼叫該無參的構造方法。如果父類只有有參的構造方法,沒有無參的構造方法,則子類必須在構造方法中必須顯式呼叫super(引數列表)來指定某個有參的構造方法。如果父類定義有無參的構造方法,但無參的構造方法宣告為private,則子類同樣必須在構造方法中必須顯式呼叫super(引數列表)來指定某個有參的構造方法。如果父類沒有其他的有參構造方法,則子類無法建立。

有父類 子類
Public無參構造方法 Private無參構造方法 有參構造方法
所有構造方法都會呼叫父類的預設構造方法
所有構造方法都會呼叫定義的無參構造方法
所有構造方法都必須指定呼叫某個有參的構造方法,或通過this呼叫某個其他的構造方法。
可以指定呼叫某個構造方法,如果沒有指定,則呼叫無參構造方法。
子類無法構造(父類無法派生子類)
所有構造方法都必須指定呼叫某個有參的構造方法,或通過this呼叫某個其他的構造方法。

例如:

<code class="hljs php has-numbering"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Parent</span> {</span>
    <span class="hljs-keyword">private</span> String pString;
    <span class="hljs-keyword">Parent</span>(){
        pString = <span class="hljs-string">"p1"</span>;
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Child</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Parent</span> {</span>
    <span class="hljs-keyword">private</span> String cString;
    Child() {
        cString = <span class="hljs-string">"c1"</span>;
    }
}</code><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li></ul><div class="save_code tracking-ad" style="display: none;" data-mod="popu_249"><a target=_blank target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png" alt="" /></a></div>

當Child物件建立時,會先呼叫父類Parent的構造方法將pString初始化為”p1”,然後再呼叫Child的構造方法,將cString初始化為”c1”。

<code class="hljs php has-numbering"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Parent</span> {</span>
    <span class="hljs-keyword">private</span> String pString;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">Parent</span>(){
        pString = <span class="hljs-string">"p1"</span>;
    }
    <span class="hljs-keyword">Parent</span>(String s){
        pString = <span class="hljs-string">"p2"</span>;
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Child</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Parent</span> {</span>
    <span class="hljs-keyword">private</span> String cString;
    Child() {
        super(<span class="hljs-string">""</span>);
        cString = <span class="hljs-string">"c1"</span>;
    }
}</code><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li></ul><div class="save_code tracking-ad" style="display: none;" data-mod="popu_249"><a target=_blank target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png" alt="" /></a></div>

由於父類定義了private的無參構造方法,因此,在子類中必須顯式指定呼叫某個有參的構造方法。

eg: class X{ Y y=new Y(); public X(){ System.out.print("X"); } } class Y{ public Y(){ System.out.print("Y"); } } public class Z extends X{ Y y=new Y(); public Z(){ System.out.print("Z"); } public static void main(String[] args) { new Z(); } }

初始化過程:  1. 初始化父類中的靜態成員變數和靜態程式碼塊 ;  2. 初始化子類中的靜態成員變數和靜態程式碼塊 ;  3.初始化父類的普通成員變數和程式碼塊,再執行父類的構造方法; 4.初始化子類的普通成員變數和程式碼塊,再執行子類的構造方法;  (1)初始化父類的普通成員變數和程式碼塊,執行  Y y=new Y();  輸出Y  (2)再執行父類的構造方法;輸出X (3) 初始化子類的普通成員變數和程式碼塊,執行  Y y=new Y();  輸出Y  (4)再執行子類的構造方法;輸出Z  所以輸出YXYZ