java中的对象创建过程

初始化的顺序为:

  先初始化父类的静态代码--->初始化子类的静态代码-->创建实例(如果不创建实例,则后面的不执行)初始化父类的非静态代码--->初始化父类构造函数--->初始化子类非静态代码--->初始化子类构造函数

  子类继承父类会先初始化父类,调用父类的构造函数,子类的构造方法的第一条语句就是调用父类的没有参数的构造方法,如果你没有写出这条语句java虚拟机就会默认的调用,如果你显示的写了这条语句,就一定要写在构造方法中的第一条语句,不然会报错。

  原理简述:只有在构造方法中调用了父类的构造方法才能继承父类的相关属性和方法,要不然子类从哪里继承父类的属性和方法,在实例化子类的时候又没有和父类有任何关系。

  子类的构造函数默认调用和这个构造函数参数一致的父类构造函数,除非在此子类构造函数的第一行显式调用父类的某个构造函数。

首先看一个类Dog:

Java代码  收藏代码
  1. package cn.tutorinfo.classloader;  
  2.   
  3. public class Dog {  
  4.     private String name;  
  5.   
  6.     // 静态成员变量  
  7.     private static DogProfile profile = new DogProfile("公"3);  
  8.   
  9.     // 静态代码块  
  10.     static {  
  11.         System.out.println("Dog的静态代码区域");  
  12.     }  
  13.   
  14.     // 静态方法  
  15.     public static void doSomething() {  
  16.         System.out.println("执行Dog类中的静态方法 doSomething()方法");  
  17.   
  18.     }  
  19.   
  20.     // 构造方法  
  21.     Dog(String name) {  
  22.         this.name = name;  
  23.   
  24.         System.out.println("Dog的名字是:" + name);  
  25.     }  
  26.   
  27.     public static void main(String[] args) {  
  28.         new Dog("京巴");    
  29.     //  Dog.doSomething();  
  30.     //  System.out.println(Dog.profile);  
  31.     }  
  32. }  
  33.   
  34. class DogProfile {  
  35.     private String male;  
  36.     private Integer age;  
  37.   
  38.     DogProfile(String male, Integer age) {  
  39.         this.male = male;  
  40.         this.age = age;  
  41.         System.out.println("DogProfile构造方法");  
  42.     }  
  43.   
  44.     @Override  
  45.     public String toString() {  
  46.         return new StringBuilder("Dog的雌雄是:").append(this.male).append(",年龄是:").append(this.age).toString();  
  47.     }  
  48. }  

 

 

 

当 main方法中代码是new Dog()时,程序的输出结果,:

Java代码  收藏代码
  1. DogProfile构造方法  
  2. Dog的静态代码区域  
  3. Dog的名字是:京巴  

 当main方法中代码是Dog.doSomething()时,程序输出结果是:

Java代码  收藏代码
  1. DogProfile构造方法  
  2. Dog的静态代码区域  
  3. 执行Dog类中的静态方法 doSomething()方法  

 当main方法中代码是System.out.println(Dog.profile) 时,程序输出结果是:

Java代码  收藏代码
  1. DogProfile构造方法  
  2. Dog的静态代码区域  
  3. Dog的雌雄是:公,年龄是:3  

 

 

Dog类中我分别设置了一个普通的属性和一个静态属性,同时类中还存在一个static 代码区域,通过分析程序的结果,我们可以大致了解了对象的创建过程:

1. 所有的类都是在对其第一次使用时,动态加载到JVM中。当首次创建类型为Dog的对象时,或者Dog类的静态方法,静态属性域首次被访问时,java解释器查找classPath,定位到Dog.class文件

 

2. 载入Dog.class文件,生成一个Class类型对象,所有有关的静态初始化动作都会执行,静态代码块,静态成员属性。 并且这种初始化动作只在Class对象首次加载时候进行一次。

 

3. 当用new Dog()创建对象时,首先JVM在堆heap上为Dog对象分配足够的存储空间

 

4. 存储空间清空,自动将Dog对象中的所有基本类型数据都设置成了默认值,对象引用被设置为null

 

5. 执行所有在字段定义处的一些初始化操作

 

6. 调用构造器方法。(没有继承)

 

如此一来,便创建了这个对象.

 

 

 

以上是不存在继承的情况下的执行过程,如果是存在多重继承的情况下呢?

首先看代码:

Java代码  收藏代码
  1. package cn.tutorinfo.classloader;  
  2.   
  3. class DogProfile {  
  4.     private String male;  
  5.     private Integer age;  
  6.   
  7.     DogProfile(String male, Integer age) {  
  8.         this.male = male;  
  9.         this.age = age;  
  10.         System.out.println("DogProfile构造方法");  
  11.     }  
  12.   
  13.     @Override  
  14.     public String toString() {  
  15.         return new StringBuilder("Dog的雌雄是:").append(this.male).append(",年龄是:").append(this.age).toString();  
  16.     }  
  17. }  
  18.   
  19. class Dog {  
  20.     private String name;  
  21.   
  22.     // 静态成员变量  
  23.     private static DogProfile profile = new DogProfile("公"3);  
  24.   
  25.     // 静态代码块  
  26.     static {  
  27.         System.out.println("Dog的静态代码区域");  
  28.     }  
  29.   
  30.     // 静态方法  
  31.     public static void doSomething() {  
  32.         System.out.println("执行Dog类中的静态方法 doSomething()方法");  
  33.   
  34.     }  
  35.   
  36.     // 构造方法  
  37.     Dog(String name) {  
  38.         this.name = name;  
  39.   
  40.         System.out.println("Dog的名字是:" + name);  
  41.     }  
  42.   
  43. }  
  44.   
  45. class JingbaDog extends Dog {  
  46.   
  47.     private static DogProfile profile = new DogProfile("母"2);  
  48.   
  49.     JingbaDog(String name) {  
  50.         super(name);  
  51.         System.out.println("JingbaDog的名字是:" + name);  
  52.   
  53.     }  
  54.   
  55. }  
  56.   
  57. public class DogExamp extends JingbaDog {  
  58.   
  59.     private static DogProfile profile = new DogProfile("母"1);  
  60.   
  61.     DogExamp(String name) {  
  62.         super(name);  
  63.         System.out.println("DogExamp的名字是:" + name);  
  64.     }  
  65.   
  66.     //生成一个DogExamp对象  
  67.     public static void main(String[] args) {  
  68.         new DogExamp("不知名");  
  69.   
  70.     }  
  71. }  

 

 

main方法中就只生成一个DogExamp对象,程序输出是:

Java代码  收藏代码
  1. 1. DogProfile构造方法  
  2. 2. Dog的静态代码区域  
  3. 3. DogProfile构造方法  
  4. 4. DogProfile构造方法  
  5. 5. Dog的名字是:不知名  
  6. 6. JingbaDog的名字是:不知名  
  7. 7. DogExamp的名字是:不知名  

 

我们结合没有继承的情况下的流程,以及上述的结果分析下:

 

java解释器在类路径中查找DogExamp.class文件后,会根据继承规则,定位JiingbaDog.class 和Dog.class. 分别载入后生成相应的Class对象,此时按照上述的流程,依次执行静态初始化的动作.

首先在Dog类中执行静态初始化,在初始化静态属性profile时,导致实例化Dogprofile对象,输出第一行。然后执行静态代码块,导致输出第二行。

接下来,子类JingbaDog中执行静态初始化动作,同样初始化了profile静态属性,导致实例化DogProfile对象,输出第三行,同理,DogExamp中的静态成员初始化,输出第4行。

 

静态初始化结束后,按照类的继承关系的构造方法的调用,首先执行基类Dog的构造方法,输出第5行

然后执行JingbaDog的构造方法,输出第6行。

 

最后执行自身的构造方法 输出第7行.

 

 

 

根据以上分析,我们得出的结论是:

1. 当首次创建一个类的对象时(此时即是调用构造方法,构造方法也是隐式的静态),或者类的静态方法被调用,静态成员属性被引用时,java解释器都将查找类对象的class文件

 

2. 载入class文件后生成Class对象时,会执行静态初始化所有动作。(包括父类的静态成员和静态代码块)

 

3. 执行类定义在字段处的初始化动作

 

4. 递归调用构造器执行构造方法

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值