1. 程式人生 > >初始化塊和構造器的比較、總結

初始化塊和構造器的比較、總結

初始化塊分為:靜態初始化塊和普通初始化塊。

在定義初始化塊時使用了static修飾符,靜態初始化塊(也叫做類初始化塊);否則,就是普通初始化塊。

與靜態方法、非靜態方法的理解其實類似,普通初始化塊負責對物件執行初始化,類初始化塊負責對類執行初始化。

為了更好地區分,上一段程式碼:

package object_down;

class Root{
	static {
		System.out.println("Root的靜態初始化塊");
	}
	{
		System.out.println("Root的普通初始化塊");
	}
	public Root(){
		System.out.println("Root的無引數的構造器");
	}
}
class Mid extends Root{
	static {
		System.out.println("Mid的靜態初始化塊");
	}
	{
		System.out.println("Mid的普通初始化塊");
	}
	public Mid() {
		System.out.println("Mid的無引數的構造器");
	}
	public Mid(String msg) {
		this(); //this()函式會在末尾進行解釋,如果此處不太理解this()函式的意思的話,請跳轉末尾
System.out.println("Mid的帶引數構造器,其引數值為:"+msg); } } class Leaf extends Mid{ static { System.out.println("Leaf的靜態初始化塊"); } { System.out.println("Leaf的普通初始化塊"); } public Leaf() { super("大學物理"); System.out.println("執行Leaf的構造器"); } } public class Test { public static void main(String[] args) { // TODO Auto-generated method stub new Leaf(); new Leaf(); } }

執行結果見下:

Root的靜態初始化塊
Mid的靜態初始化塊
Leaf的靜態初始化塊
Root的普通初始化塊
Root的無引數的構造器
Mid的普通初始化塊
Mid的無引數的構造器
Mid的帶引數構造器,其引數值為:大學物理
Leaf的普通初始化塊
執行Leaf的構造器
Root的普通初始化塊
Root的無引數的構造器
Mid的普通初始化塊
Mid的無引數的構造器
Mid的帶引數構造器,其引數值為:大學物理
Leaf的普通初始化塊
執行Leaf的構造器

為啥生成兩個Leaf()物件,卻要執行那麼多的函式呢?

答案見下:

第一次建立一個Leaf()物件時,因為系統中還不存在Leaf()類,因此需要先載入並初始化Leaf類。

而初始化Leaf類其實也是一個蠻麻煩的過程:初始化Leaf類需要先執行其頂層父類的靜態初始化塊(因為是對類初始化的嘛!),再執行其直接父類的靜態初始化塊,最後才執行Leaf本身的靜態初始化塊。

一旦Leaf類初始化成功後,Leaf類在JVM中將一直存在,因此當第二次建立Leaf例項時,無需再次對Leaf類進行初始化。

每次建立一個Leaf物件時,都需要先執行最頂層的父類的初始化塊,構造器,然後再執行其父類的初始化塊、構造器……最後才執行Leaf的初始化塊,構造器。(注意:建立物件時執行的初始化塊是普通初始化塊,它負責對物件執行初始化)

最後,上面程式碼中有一段中有一個this()函式,在此作以下解釋:

package test_test;

import java.util.*;

public class Test {
    private int x;
    private int y;
    private int z;
   
    public Test(int x, int y) {
        this.x = x;
        this.y = y;
        System.out.println("Test的含有兩個引數的構造器");
    }

    public Test(int x, int y, int z) {
        this(x,y);
        this.z = z;
        System.out.println("Test的含有三個引數的構造器");
    }
    
    public static void main(String []args) {
    	new Test(100,10);
    	System.out.println("-------------------------");
    	new Test (1, 2,3);
    }

}

輸出結果:

Test的含有兩個引數的構造器
-------------------------
Test的含有兩個引數的構造器
Test的含有三個引數的構造器
this()方法只能用在建構函式中,同時為了避免操作物件時物件還未構建成功,需要this()和super()的呼叫在第一行實現【以此來建立物件】,防止異常。

相關推薦

初始構造比較總結

初始化塊分為:靜態初始化塊和普通初始化塊。在定義初始化塊時使用了static修飾符,靜態初始化塊(也叫做類初始化塊);否則,就是普通初始化塊。與靜態方法、非靜態方法的理解其實類似,普通初始化塊負責對物件執行初始化,類初始化塊負責對類執行初始化。為了更好地區分,上一段程式碼:p

Java中的初始構造的執行順序

我們都知道java中不但有構造器,還有初始化塊和靜態初始化塊的概念,今天我們就來看看他們之間的執行順序是怎樣的。 我們來看一個例子: package test; class Root { static { System.out.println("Root的靜態初始化塊"); }

C++構造函數對類成員變量初始,使用初始列表構造函數內部直接賦值 的差別

初始化列表 不能 構造 調用 ron 二次 art size strong 初始化和賦值對內置類型的成員沒有什麽大的差別,像任一個構造函數都能夠。但有的時候必須用帶有初始化列表的構造函數: (1) 成員類型是沒有默認構造函數的類。若沒有提供顯式初始化時,則編譯器隱式

java中的初始靜態

java語言中的初始化塊 1、什麼是初始化塊? 在一個類中,用來對例項變數作初始化的語句塊。2、初始化塊在何時被執行? 它在每一次構造物件時被執行且比構造器先執行。3、對例項變數做初始化有三種方式? 1) 通過構造器實現初始化。 2) 在定義例項變數時就給它一個值。 3)

Java類成員變數普通成員變數初始構造方法的初始執行順序

 序言   關於類的static成員變數初始化、static初始化塊、例項的普通成員變數初始化、例項的普通初始化塊以及建構函式的執行順序,我一直不是十分明確地知道,今天專門花了幾個小時的時間參考網上資料設計出了比較明瞭的測試程式碼,有程式碼有結果有真相。總體而言,sta

Java構造方法靜態初始非靜態初始的區別用途

Static init Main. Static init A. Static init B. Static init C. Instance init A. Constructor A. Instance init B. Constructor B. Instance init C. Constructor

Java初始順序(靜態變量靜態初始實例變量實例初始構造方法)

靜態初始化 都對 class block 註釋 執行順序 blog 中一 成員變量 1、執行順序 1.1、一個類中的初始化順序 (靜態變量、靜態初始化塊)=>(變量、初始化塊、構造器)。 1.2、兩個具有繼承關系類的初始化順序 父類的(靜態變量、

初始構造初始的區別

zed ali ati ise reat div cto 練習 diff // initialization/ConstructorTest2.java // TIJ4 Chapter Initialization, Exercise 2, p158 /* Create

構造方法類的初始以及類欄位的初始順序

構造方法 首先,以下程式碼為何無法通過編譯?哪兒出錯了? public class Test { public static void main(String[] a

tf.get_variable 中變數初始函式Xavier初始

當使用 tf.get_variable(name, shape=None, initializer=None) 來定義變數時,可以利用變數初始化函式來實現對 initializer 的賦值。 在神經網路中,最常權重賦值方式是 正態隨機賦值 和 Xavier賦值。 1. 變數初始

Java的知識點10——static關鍵字靜態初始 引數傳值機制匯入類import 靜態匯入

static 關鍵字 在類中,用static宣告的成員變數為靜態成員變數,也稱為類變數。 類變數的生命週期和類相同,在整個應用程式執行期間都有效。它有如下特點:   1. 為該類的公用變數,屬於類,被該類的所有例項共享,在類被載入時被顯式初始化。   2. 對於該類的所

2018年11月13日Java學習之關鍵字static(類成員類方法),單例設計,類的成員之:初始

1.類變數(類屬性)由該類的所有例項共享 static 修飾的變數就是類變數,可以直接不建立物件訪問靜態成員,所有例項可以共同修改這個值 2.類方法 static修飾的方法可以用類名.方法名()訪問 在static方法內部只能訪問類的static屬性,不能訪問

Java-為什麼非靜態內部類裡面不能定義靜態方法靜態成員變數靜態初始

首先要明確一點: static修飾方法、成員變數是屬於類自己的。並不屬於特定的某個物件。所以我們可以像這樣使用static修飾的方法、變數:ClassName.methodName、ClassName

C++初始列表大括號裡構造的區別

C++的物件建構函式有兩種初始化的方法: 1、初始化列表 2、大括號裡面賦值 這兩種推薦使用第二種,原因在於使用初始化列表只需要進行一次初始化,而使用大括號內賦值的話首先需要呼叫預設建構函式初始化,然後再進行賦值,效率上明顯前者更優。

JAVA中面向物件基礎:抽象類初始

本文轉載連線為:http://android.yaohuiji.com/archives/3241 一、抽象類 用 abstract 修飾的類定義,我們稱之為抽象類,抽象類不能被例項化。 用 abstract 修飾的方法,我們稱之為抽象方法,抽象方法不能有方法體。 面向物

C++陣列(一維二維三維)的動態分配new初始memset釋放delete

【原文】http://blog.csdn.net/shanzhizi/article/details/7835752 陣列的動態分配、初始化和釋放經常用到,這裡總結一下,尤其是二維陣列 一維陣列 一維陣列的動態分配,初始化和撤銷都好說,幾乎每一本C++教材都會做出詳細的說明

java靜態方法,靜態初始及靜態變數的宣告初始不能使用泛型的原因

最近學習到了Java中的泛型,對於靜態方法,靜態初始化塊及靜態變數的宣告和初始化不能使用泛型的原因做了一個彙總: 1。因為泛型是要在物件建立的時候才知道是什麼型別的,而物件建立的程式碼執行先後順序是static的部分,然後才是建構函式等等。所以在物件初始化之前static的

CTP: 初始成功TradeAPIMDAPI登陸成功

     在CTP中,如果CTP初始化、TradeAPI、MDAPI登陸都成功,表明CTP真實連線上,但有時是CTP初始化沒有成功,但TradeAPI、MDAPI傳回的資訊表明,登陸都成功,這時CTP實際上和客戶端之間也是沒有真實連上的。     成功的例子: 2015-0

java靜態初始例項初始

public class Demo1 { public Demo1() { System.out.println("父類構造器"); } static{ System.out.println("父類靜態初始化塊"); } { System.out.pr

Effective Java - 構造私有列舉單例

目錄 餓漢式單例 靜態常量 靜態程式碼塊 懶漢式單例 嘗試加鎖 同步程式碼塊 雙重檢查 靜