1. 程式人生 > >父類構造器的隱式呼叫和顯式呼叫

父類構造器的隱式呼叫和顯式呼叫

當呼叫某個類的構造器來建立Java物件時,系統總會先呼叫父類的非靜態初始化塊進行初始化.這個呼叫是隱式執行的,而且父類的靜態初始化塊總是會被執行.接著會呼叫父類的一個或多個構造器執行初始化,這個呼叫既可以是通過super進行顯式呼叫,也可以是隱式呼叫.

當所有父類的非靜態初始化塊,構造器一次呼叫完成後,系統呼叫本類的非靜態初始化塊,構造器執行初始化,最後返回本類的例項.

假設有如此的類繼承結構Object<--Parent<--Mid<--Sub.那麼,對於這樣的類繼承結構(Java程式裡所有類的最終父類都是java.lang.Object類),如果在程式中建立Sub物件,程式會按如下步驟進行初始化.

1)執行Object類非靜態初始化塊(如果有的話).

2)隱式或顯式呼叫Object類的一個或多個構造器執行初始化.

3)執行Parent類非靜態初始化塊(如果有的話).

4)隱式或顯式呼叫Parent類的一個或多個構造器執行初始化.

5)執行Mid類非靜態初始化塊(如果有的話).

6)隱式或顯式呼叫Mid類的一個或多個構造器執行初始化.

7)執行Sub類非靜態初始化塊(如果有的話).

8)隱式或顯式呼叫Sub類的一個或多個構造器執行初始化.

下面程式演示了建立Java物件時的初始化過程
package com.lic.array;

public class Demo13 {

	public static void main(String[] args) {
		new Wolf(2.3);
	}
}
class Creature{
	{
		System.out.println("Creature的非靜態初始化塊");
	}
	// 下面定義兩個構造器
	public Creature(){
		System.out.println("Creature無引數構造器");
	}
	public Creature(String name){
		// 使用this呼叫另一個過載,無引數的構造器
		this();
		System.out.println("Creature帶有一個引數的構造器,name引數:"+name);
	}
}
class Animal extends Creature{
	{
		System.out.println("Animal的非靜態初始化塊");
	}
	public Animal(String name){
		super(name);
		System.out.println("Animal帶一個引數的構造器,name引數:"+name);
	}
	public Animal(String name, int age){
		// 使用this呼叫另一個過載的構造器
		this(name);
		System.out.println("Animal帶2個引數的構造器,其中age:"+age);
	}
}
class Wolf extends Animal{
	{
		System.out.println("Wolf的非靜態初始化塊");
	}
	public Wolf(){
		// 顯式呼叫父類有2個引數的構造器
		super("灰太狼",3);
		System.out.println("Wolf無引數的構造器");
	}
	public Wolf(double weight){
		// 使用this呼叫另一個過載的構造器
		this();
		System.out.println("Wolf的帶weight引數的構造器,weight引數:"+weight);
	}
}
/**
 * 子類構造器會顯式或隱式的呼叫父類構造器,預設呼叫無參構造器.如果父類定義了有參構造器且未定義無參構造器,則必須顯式呼叫父類已經宣告的構造器.
*/
控制檯輸出如下:
Creature的非靜態初始化塊
Creature無引數構造器
Creature帶有一個引數的構造器,name引數:灰太狼
Animal的非靜態初始化塊
Animal帶一個引數的構造器,name引數:灰太狼
Animal帶2個引數的構造器,其中age:3
Wolf的非靜態初始化塊
Wolf無引數的構造器
Wolf的帶weight引數的構造器,weight引數:2.3
上面程式定義了Creature,Animal,Wolf這3個類,其中Animal是Creature的子類,Wolf是Animal的子類.3個類都包含了非靜態初始化塊,構造器成分.當程式呼叫Wolf的指定構造器建立Wolf例項時,程式會按上面介紹的初始化步驟執行初始化.執行上面程式,結果如上圖所示.

只要在程式建立Java物件,系統總是先呼叫最頂層父類的初始化操作,包括吃實話塊和構造器,然後依次向下呼叫所有父類的初始化操作,最終執行本類的初始化操作返回本類的例項.至於呼叫父類的哪個構造器執行初始化,則分為如下幾種情況:

1)子類構造器執行體的第一行程式碼使用super顯式呼叫父類構造器,系統根據super呼叫裡傳入的實參列表來確定呼叫父類的哪個構造器;

2)子類構造器執行體的第一行程式碼使用this顯式呼叫本類中過載的構造器,系統將根據this呼叫裡傳入的實參列表來確定本類的另一個構造器(執行本類中另一個構造器時即進入第一種情況);

3)子類構造器執行體中既沒有super呼叫,也沒有this呼叫,系統將會在執行子類構造器之前,隱式呼叫父類無引數的構造器.

super呼叫用於顯式呼叫父類的構造器,this呼叫用於顯式呼叫本類中的另一個過載的構造器.super呼叫和this呼叫都只能在構造器中使用,而且super呼叫和this呼叫都必須作為構造器的第一行程式碼,因此構造器中的super呼叫和this呼叫最多隻能使用其中之一,而且最多隻能呼叫一次.


相關推薦

構造呼叫呼叫

當呼叫某個類的構造器來建立Java物件時,系統總會先呼叫父類的非靜態初始化塊進行初始化.這個呼叫是隱式執行的,而且父類的靜態初始化塊總是會被執行.接著會呼叫父類的一個或多個構造器執行初始化,這個呼叫既可以是通過super進行顯式呼叫,也可以是隱式呼叫. 當所有父類的非靜態初

Super關鍵字呼叫構造

一、子類不會獲得父類的構造器,但子類構造器裡可以呼叫父類構造器初始化程式碼。 1.1 在一個構造器中呼叫另一個過載的構造器,使用this呼叫來完成。如下程式碼段: public class C

PHP面向物件開發,關於呼叫構造的問題

今天進行PHP開發時,發現子類的構造方法的引數必須與父類的構造方法引數一樣,否則會在網頁上進行警告,影響網頁的美觀。 目前的解決方法有三個: 1.通過調整PHP的錯誤提示等級。 2.使用父類的建構函式,子類的屬性單獨賦值。 3.解決方法如下: class a{ var $

構造呼叫構造的順序問題

一 super呼叫父類構造器 子類構造器總會呼叫父類構造器。 如果子類構造器沒有顯示使用super呼叫父類構造器,子類構造器預設會呼叫父類無參構造器。 建立一個子類例項時,總會呼叫最頂層父類構造器。 二 構造器呼叫順序示例 1 程式碼示例 class Creature { public Creature(

構造關係

父類:Base   子類:Driver 1.子父類都是預設構造器: 父類: 子類: 執行結果: 分析: 如果父類base   class只有預設建構函式,也就是編譯器自動為你產生的,而子類

轉換轉換

string 運算 依次 col 指向 pri ast 現象 style C/C++對於數據類型的轉換包括隱式轉換和顯式轉換(強制類型轉換)。 一般來說,隱式轉換包括以下幾種情形: 1. 低精度與高精度混合運算,低精度會隱式轉換成高精度類型。 int a = 10; do

java引數引數

      隱式引數:是呼叫函式的物件,在類的方法中呼叫了類的例項域,這個被呼叫的例項域就是隱式引數。或者說是當前方法的物件, 一般我們會使用this關鍵字來使用隱式引數,this表示呼叫該方法的當前類的當前例項,使用this關鍵字可以很好的把顯式引數和隱式引

Selenium中的等待等待

在Selenium中,“等待”在執行測試中起著重要作用。在本文中,您將學習Selenium中“隱式”和“顯式”等待的各個方面。 在本文中,您將學習 - 2. 隱瞞等待 3. 明確等待 4. 流利的等待 為什麼我們需要在Selenium中等待? 大多數Web應用

PostgreSQL中的連線連線

連線有多種形式,例如內連線,外連線,交叉連線,自連線等。但是最重要的區別之一是隱式連線和顯式連線之間的區別。 隱式連線 FROM子句後面直接列出多個表名,這種連線方式即屬於內連線,是隱式連線。 示例: postgres=# CREATE TABLE test_1(id int, cl

selenium的等待等待及cookie操作

頁面等特: 現在的網頁越來越多采用了Ajax技術,這樣程式便不能確定何時某個元素完全加載出來,入股實際頁面等待時間過長導致某個dom元素還沒出來,但是你的程式碼直接使用了這個 Webelement,那麼就會上Nullpointerf的異常,為了解決這個問題,所以 Selenium提 供了兩種等待方

C++型別的轉換轉換

隱式轉換:編譯器根據需要自動轉換變數型別。 1、一些基本型別的轉換 double d = 82.0; int i = d; 2、類的隱式轉換,以下幾種情況,類B能隱式轉換成類A: (1)B公有繼承A,然後用子類去初始化基類 class B: class A{} A a;

python網路資料探勘--JS等待等待

第一部分:隱式等待和顯式等待      隱式等待和顯式等待的不同之處在於,隱式等待是等DOM中某個狀態發生改變後再繼續執行程式碼(沒有明確的等待時間,但是有最大等待期限,只要在時限內就可以),而顯式等待明確設定了等待時間,如上篇文章中等待三秒鐘。在隱式等待中,DOM被觸發的

第五章 的繼承super的使用呼叫構造方法

類的繼承 mammals dogs cats humans lions tigers leopards 人是哺乳動物,因為人都具有哺乳動物的所有特徵,但哺乳動物卻不一定是人。哺乳動物類和人類之間就存在繼承關係(IS-A

Java 構造呼叫成員初始化順序

呼叫基類構造器。首先構造繼承關係最上層類的構造器,然後是下一層匯出類的構造器,以此類推,直至最底層的匯出類。 按宣告順序呼叫成員的初始化方法。 呼叫匯出類構造器的主體。 demo class

C# 關鍵字explicit(顯示),implicit(),型的轉換

tar oid bsp color col 必須 code 類型 顯示 class Program { static void Main(string[] args) { Adaptee ada = ne

對象序列化中 子構造函數的調用問題

images png http 分享 com 函數 對象 情況 序列 第三種情況: 對象序列化中 子類和父類構造函數的調用問題

Java裡子呼叫構造方法問題

 在Java中,子類的構造過程中,必須呼叫其父類的建構函式,是因為有繼承關係存在時,子類要把父類的內容繼承下來,通過什麼手段做到的?        答案如下:         當你new一個子類物件的時候,必須首

關於Java中基構造呼叫問題

在《Java程式設計思想》第7章複用類中有這樣一段話,值得深思。當子類繼承了父類時,就涉及到了基類和匯出類(子類)這兩個類。從外部來看,匯出類就像是一個與基類具有相同介面的新類,或許還會有一些額外的方法和域。但繼承並不只是複製基類的介面。當建立一個匯出類物件時,該物件包含了一個基類的子物件,這個子物件與你用

java構造方法,以及super、this關鍵字、呼叫呼叫

首先需要明白的是,當建立java物件時,程式總是依次呼叫每個父類的非靜態初始化塊、父類構造器(總是從Object開始)執行初始化,最後才呼叫該類的非靜態初始化塊、構造器執行初始化。 為了說明問題,這裡貼出一個小例子: class Parent{static{System.

構造方法呼叫構造方法(super關鍵字的使用)

package kaoshi; /** ************************************ * @author Hejing * @date 2017年12月24日 * @class fisrt.java * ***********