關於父類和子類的初始化問題
阿新 • • 發佈:2019-02-18
在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