靜態程式碼區塊、靜態成員變數->非靜態程式碼區塊、非靜態成員變數->new其他物件呼叫對應物件建構方法(在本地物件的方法外包含建構方法)->new本地物件呼叫建構方法。
【注意:若new物件時,該物件中有靜態程式碼區塊和非靜態程式碼區塊,每new一次對象,非靜態程式碼區塊都會執行一次,但靜態程式碼區塊只會執行一次往後new物件都不會再執行。 】
各種程式碼區塊的定義
class Demo{ static { //静态代码块...... } }
關於靜態程式碼區塊再詳細介紹下
由於JVM在載入類別時會執行靜態程式碼區塊,所以靜態程式碼區塊先於主方法執行。如果類別中包含多個靜態程式碼區塊,那麼將按照"先定義的程式碼先執行,然後再定義的程式碼後執行"。 【注意:1 靜態程式碼區塊不能存在於任何方法體內。 2 靜態程式碼區塊不能直接存取靜態實例變數和實例方法,需要透過類別的實例物件來存取。 】 實例代碼塊 實例代碼塊 又叫 構造初始化塊 , 構造代碼塊 , 初始化塊 。
class Demo{ { //实例代码块...... } }
class Demo{ public void test(){ { //局部代码块...... } } }
驗證各程式碼區塊的執行順序範例程式碼如下:
class Init {
public Init() {
System.out.println("无参构造器");
}
public Init(int a) {
System.out.println("有参构造器");
}
{
System.out.println("实例代码块1");
}
{
System.out.println("实例代码块2");
}
{
System.out.println("实例代码块3");
}
static {
System.out.println("静态初始化块1");
}
static {
System.out.println("静态初始化块2");
}
public void method(){
{
System.out.println("普通初始化块");
}
}
}
class Demo {
public static void main(String[] args) {
Init init1 = new Init();
init1.method();
System.out.println("------------");
Init init2 = new Init();
init2.method();
//多打印几个对象的目的是:方便看出Static静态代码块 是否只执行一次!!!
System.out.println("------------");
Init init3 = new Init();
init3.method();
}
}
結論:
執行順序為:靜態程式碼區塊>實例程式碼區塊> 建構子>普通程式碼區塊,
且靜態程式碼區塊,類別載入的時候就會調用,並且只調用一次(隨著類別的載入而執行)。
那麼類別什麼時候會被載入呢?
- 建立物件實例時(new)
- 建立子類別物件實例,父類別也會被載入- 使用類別的靜態成員時(靜態屬性,靜態方法)
驗證存在繼承關係中各程式碼區塊的執行順序
,
#程式碼如下:class One {
public One() {
System.out.println("One构造器");
}
{
System.out.println("One实例化块");
}
static {
System.out.println("One静态代码块");
}
}
class Two extends One {
public Two() {
System.out.println("Two构造器");
}
{
System.out.println("Two实例化块");
}
static {
System.out.println("Two静态代码块");
}
}
class Three extends Two {
public Three() {
System.out.println("Three构造器");
}
{
System.out.println("Three实例化块");
}
static {
System.out.println("Three静态代码块");
}
}
//测试代码 如下:
public class Demo {
public static void main(String[] args) {
Three three = new Three();
System.out.println("-----");
Three three1 = new Three(); //重复执行的目的是为了 验证static是否只执行一次
System.out.println("-----");
Two three2 = new Three(); //验证 多态的情况下 用后面的类进行初始化 结果和上面一样
}
}
結論:
多個類別的繼承中初始化區塊、靜態初始化區塊、建構器的執行順序為:
父类静态块——>子类静态块——>父类实例代码块——>父类构造器——>子类实例代码块——>子类构造器 ——>(如果有局部代码块, 再正常执行即可, 这里就没必要进行测试了) 我们那一段代码作为例子说明下,代码如下: 接下来让我们看看 , Init.java编译完的的字节码文件(Init.class) 从这个字节码文件就可以很清晰的看出, 实例代码块实际上是被依次放到了构造方法的第一句, 所以可以的出此结论: 实例代码块的执行顺序是优先于构造器的。 以上是程式碼區塊和構造器在Java物件初始化時的呼叫順序是什麼?的詳細內容。更多資訊請關注PHP中文網其他相關文章!通过字节码深究实例代码块优先于构造器原因
class Init {
public Init() {
System.out.println("无参构造器");
}
public Init(int a) {
System.out.println("有参构造器");
}
{
System.out.println("实例代码块1");
}
{
System.out.println("实例代码块2");
}
{
System.out.println("实例代码块3");
}
static {
System.out.println("静态初始化块1");
}
static {
System.out.println("静态初始化块2");
}
public void method(){
{
System.out.println("普通初始化块");
}
}
}