对象创建的过程(重点理解)

 

1.思考下列代码的执行过程:

public class TestSingleObject {
    
    private int cnt = 1;  //成员变量
    
     //构造块
    { 
        cnt = 2;    
    }
    
    // 构造方法
    public TestSingleObject() {
        cnt = 3;
    }
    
    public static void main(String[] args) {
        
        TestSingleObject tso = new TestSingleObject();
        System.out.println("tso.cnt = "+tso.cnt);
    }
    

}

 

打印结果是:   3

执行过程:

- main()方法是程序的入口,进行类的加载     

- new TestSingObject(); 

先对实例变量根据数据类型进行默认初始化赋值  ---   int cnt =0;

然后执行 private int cnt = 1;  ---- cnt = 1;

然后执行 构造块 {cnt=2;}         ----cnt = 2;

最后执行  构造方法                 -----cnt =3;

-执行system...("cnt")                ------打印出结果到控制台:tso.cnt = 3

 

重点: 构造块{ } 的执行顺序优于 构造方法


 

2.在理解以上内容的基础上,加入 static静态相关的代码看看:

public class Dad {
    
   public Dad() {
        System.out.println("Dad类中的构造方法Dad(){}");
    }

{
System.out.println("Dad类中的构造块{}");
}

static { System.out.println("Dad类中的静态构造块static{}"); } public static void main(String[] args) { Dad dad = new Dad(); } }

 

 

 执行结果:

Dad类中的静态构造块static{}
Dad类中的构造块{}
Dad类中的构造方法Dad(){}

执行顺序:

 -程序运行,即启动jvm虚拟机,进行 Dad.class类文件的加载

-static修饰的变量和方法 在类加载时期进行,其中static{ }静态构造块只会执行一次

  执行  static { System.out.println("Dad类中的静态构造块static{}"); }

-mian()方法是程序的入口,执行   Dad dad = new Dad(); 创建对象,先给成员属性赋对应属于类型的默认值。再执行构造块、最后执行构造方法

  - 执行  { System.out.println("Dad类中的构造块{}"); }

 -执行  Dad() { System.out.println("Dad类中的构造方法Dad(){}"); }

 


 

3.再加入继承 方面的知识 试一试

 

public class Dad {    //父类
    
    {
        System.out.println("Dad类中的构造块{}");
    }
    
    public Dad() {
        System.out.println("Dad类中的构造方法Dad(){}");
    }
    static {
        System.out.println("Dad类中的静态构造块static{}");
        
    }
            
}

 

public class Son extends Dad {   // 子类继承父类
    

    {
        System.out.println("Son类中的构造块{}");
    }
    
    public Son() {
        System.out.println("Son类中的构造方法Son(){}");
    }
    static {
        System.out.println("Son类中的静态构造块static{}");
        
    }
}

 

 

public class Test {  //测试代码
    
    public static void main(String[] args) {
        
        Son s = new Son();   // 创建子类对象
    }
    
    
}

 

 

 控制台结果

Dad类中的静态构造块static{}
Son类中的静态构造块static{}
Dad类中的构造块{}
Dad类中的构造方法Dad(){}
Son类中的构造块{}
Son类中的构造方法Son(){}

 

 

 执行顺序:

 -程序运行,jvm虚拟机启动,类加载时期:

  先执行父类的静态构造块,

  再执行子类的静态构造块,

 

-main()方法,程序的入口,执行 Son s = new Son(); // 创建子类对象

  先执行 父类的构造块, 

  再执行 父类的构造方法,

  然后才执行 子类的构造块,

  执行子类的构造方法, 

重点:static通常用来修饰属性和方法,被static修饰的属性和方法都隶属于 类层级(区别于对象层级),类层级的东西随着 类的加载而加载。


最后分析一道阿里面试题:

public class Text {                       // 1.程序运行,启动jvm虚拟机,进入类加载时期
        public static int k = 0  ;    
        public static Text t1 = new Text("t1") ;  
        public static Text t2 = new Text("t2") ;  
        public static int i = print("i") ;  
        public static int n =99 ;  
        public int j = print("j") ;  
        
        {  
            print("构造块");  
          
        }  
        static {  
            print("静态块");  
        }  
        public Text(String str){  
            System.out.println((++k)+":"+str+"   i="+i+"    n="+n) ;  
            ++i;++n ;  
        }  
        public static int print(String str){  
            System.out.println((++k)+":"+str+"   i="+i+"    n="+n) ;  
            ++n;  
            return ++i ;  
        }  
        public static void main (String args[]){  
             Text t = new Text("init") ;  
        }  
    }  

 

 

结果

1:j   i=0    n=0
2:构造块   i=1    n=1
3:t1   i=2    n=2
4:j   i=3    n=3
5:构造块   i=4    n=4
6:t2   i=5    n=5
7:i   i=6    n=6
8:静态块   i=7    n=99
9:j   i=8    n=100
10:构造块   i=9    n=101
11:init   i=10    n=102

 



 

 

posted @ 2019-10-24 18:53  小茅棚  阅读(326)  评论(0编辑  收藏  举报