zoukankan      html  css  js  c++  java
  • Java的初始化执行顺序(父类static变量->子类static变量->父类成员变量->父类构造器->成员变量->构造器->main函数)

    1. 引言

    了解Java初始化的顺序,有助于理解Java的初始化机制和内存机制

    顺序:父类static变量->子类static变量->父类成员变量->父类构造器->成员变量->构造器->main函数(说明:static变量包括static变量和static代码块,按位置顺序执行)

    2. 样例

    2.1 无继承的类的初始化顺序

    public class TestClass {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		System.out.println("Creating new Cupboard() in main");
    		new Cupboard();
    		System.out.println("Creating new Cupboard() in main");
    		new Cupboard();
    		t2.f2(1);
    		t3.f3(1);
    	}
    
    	static Table t2 = new Table();
    	static Cupboard t3 = new Cupboard();
    }
    
    // : StaticInitialization.java
    // Specifying initial values in a
    // class definition.
    
    class Bowl {
    	Bowl(int marker) {
    		System.out.println("Bowl(" + marker + ")");
    	}
    
    	void f(int marker) {
    		System.out.println("f(" + marker + ")");
    	}
    }
    
    class Table {
    	static Bowl b1 = new Bowl(1);
    	
    	static{
    		System.out.println("Table() static 1");
    	}
    
    	Table() {
    		System.out.println("Table()");
    		b2.f(1);
    	}
    
    	void f2(int marker) {
    		System.out.println("f2(" + marker + ")");
    	}
    	
    	Bowl b10 = new Bowl(10);
    	
    	{
    		System.out.println("Table() non-static");
    	}
    	
    	Bowl b11 = new Bowl(11);
    
    	static Bowl b2 = new Bowl(2);
    	
    	static{
    		System.out.println("Table() static 2");
    	}
    }
    
    class Cupboard {
    	Bowl b3 = new Bowl(3);
    	static Bowl b4 = new Bowl(4);
    
    	Cupboard() {
    		System.out.println("Cupboard()");
    		b4.f(2);
    	}
    
    	void f3(int marker) {
    		System.out.println("f3(" + marker + ")");
    	}
    
    	static Bowl b5 = new Bowl(5);
    }
    

    输出的结果如下:

    Bowl(1)
    Table() static 1
    Bowl(2)
    Table() static 2
    Bowl(10)
    Table() non-static
    Bowl(11)
    Table()
    f(1)
    Bowl(4)
    Bowl(5)
    Bowl(3)
    Cupboard()
    f(2)
    Creating new Cupboard() in main
    Bowl(3)
    Cupboard()
    f(2)
    Creating new Cupboard() in main
    Bowl(3)
    Cupboard()
    f(2)
    f2(1)
    f3(1)
    

    2.2 有继承的类的初始化顺序

    //: Beetle.java 
    	// The full process of initialization. 
    	 
    	class Insect { 
    	  int i = 9; 
    	  int j; 
    	  Insect() { 
    	    prt("i = " + i + ", j = " + j); 
    	    j = 39; 
    	  }
    	  static{
    		  System.out.println("Insert static block0");
    	  }
    	  
    	  static int x1 =  
    	    prt("static Insect.x1 initialized"); 
    	  static int prt(String s) { 
    	    System.out.println(s); 
    	    return 47; 
    	  }
    	  static{
    		  System.out.println("Insert static block1");
    	  }
    	} 
    	
    	public class Beetle extends Insect { 
    		  int k = prt("Beetle.k initialized"); 
    		  Beetle() { 
    		    prt("k = " + k); 
    		    prt("j = " + j); 
    		  } 
    		  static int x2 = 
    		    prt("static Beetle.x2 initialized"); 
    		  static int prt(String s) { 
    		    System.out.println(s); 
    		    return 63; 
    		  } 
    		  public static void main(String[] args) { 
    		    prt("Beetle constructor"); //flag 1
    		    Beetle b = new Beetle(); //flag 2
    		  } 
    		} ///:~ 
    

    输出的结果如下:

    Insert static block0
    static Insect.x1 initialized
    Insert static block1
    static Beetle.x2 initialized
    Beetle constructor
    i = 9, j = 0
    Beetle.k initialized
    k = 63
    j = 39
    
    //如果只把flag 1 那条语句注释掉,输出内容如下:
    Insert static block0
    static Insect.x1 initialized
    Insert static block1
    static Beetle.x2 initialized
    i = 9, j = 0
    Beetle.k initialized
    k = 63
    j = 39
    
    //如果只把flag 2 那条语句注释掉,输出内容如下:
    Insert static block0
    static Insect.x1 initialized
    Insert static block1
    static Beetle.x2 initialized
    Beetle constructor
    

    3. 总结

    只要按照这个顺序:父类static变量->子类static变量->父类成员变量->父类构造器->成员变量->构造器->main函数(说明:static变量包括static变量和static代码块,按位置顺序执行), 去推导初始化执行顺序就能得到正确的执行答案数据。

    注意点:

    1.若仅仅执行static方法,则只会执行该类及其父类的所有静态变量,而且静态变量只会被执行一次

    2.当对象被new出来时,才会开始初始化该类及其父类的所有变量,按照以上的说的顺序执行

    3.成员或者静态static变量若申明时不赋值,会被初始化相应类型的默认值,例如int是0,String是null等

    4.可以用debug模式直接断点调试,跟着走一遍,就能看到代码是怎么初始化变量的(当然,自己先演练一遍,效果更好)

    4.参考

    Thinking in Java P113, P158

  • 相关阅读:
    Android ListView 的布局图标大小设置
    Android BaseAdapter 类 重写模版
    Fabric 介绍
    CentOS yum安装mysql
    JavaStringBuffer类常用方法简介
    Java流的简单使用:读取文件、写入文件(面试题:删除注释代码)
    Android数据库详解之二:数据库用法介绍
    JavaString类的方法及说明
    Android图像识别项目OpenCV(1):技术选型以及NDK搭建
    JDK(6u25)安装及相关知识
  • 原文地址:https://www.cnblogs.com/fanbi/p/7485381.html
Copyright © 2011-2022 走看看