Java程序运行和对象创建过程简述
2017-06-22 22:12
369 查看
Java中一个对象创建分为两个步骤: 加载类,创建对象。
加载类是将所写的程序.java文件编译生成的.class文件加载到内存中,保证了对象创建的预置环境。类加载完毕后才可以创建该类的对象。
第一步:加载类
1. 当开始运行一个类,虚拟机首先试图访问指定启动类的 .main() 方法,加载该类的 .class 文件。
2. 如果该类有父类,那么继续加载其父类,以此类推,直到加载出所有与main入口类相关的类(它的父类,父类的父类等)。
3. 接着,从其顶级父类开始,对其static域按照顺序进行初始化!直至初始化完所有类的static域。>将static域放到静态存储区。
4. 至此类的加载工作完毕了,下面就进入main函数,执行main函数。一般main函数中来创建类的对象,如果发现要创建的类没有被加载,则继续加载该类)
第二步:对象创建
1. 为对象获取内存,然后将内存全部置为0,此时对象中的所有属性都是被赋予0的默认值(内存为0时候的默认值:null-对象引用,0-int,false-boolean...)> 在堆中生成对象所需空间,全部初始化为0,具体成员属性值为堆上对应内存子块--正是因为这种机制,所以java可以保证所有的类对象的属性都会被初始化,但是局部不会被初始化。
这里需要注意的是:一个对象内部组合了另一个对象,那么在堆中其实存的也是一个引用,这个引用指向被组合对象的堆内存地址(另外再创建)。
当引用在内存的二进制数据都为0的时候,他的表现形式是null;当他指向的数据内容内存区数据都是0的时候,他的值为0,"",False等初始标准值。所谓初始化就是修改内存区的二进制数据,因为对象在创建时候第一步就将内存清0,所以保证了所有属性都能至少被初始化为标准初值!
但是局部变量不一样,你不初始化,只是申明,那么开辟的内存区在栈中值会是一个未知数据(一旦使用该引用的话,使用的可能是你没有初始化而瞎几把乱指的地址)所以Java会代码检验的时候发现你使用了未初始化的引用,直接给予不通过,直接杜绝了这种可能性的发生。
综上,Java中使用任何变量或引用,必须初始化,初始化就是将内存中旧的二进制数据要么清0,要么赋予你要赋的值!
2. 从顶级父类开始,按照申明顺序将给顶级父类的非static的成员属性初始化(static的只初始化一次在类加载阶段)> 用属性定义的值覆盖0值。
3. 调用顶级父类的构造函数,如果有成员属性初始化则覆盖前一个申明时初始化值。> 构造函数再次初始化,覆盖前面申明时初始化。
4. 以此类推,将所有的父级(先初始化属性,在调用构造,一层一层的构造完毕) 构造完成
5. 最后,初始化当前类的非static属性,再调用当前类的构造函数,完成所有初始化工作。
注意:
1、类中static部分是发生在类加载时期的,并且只初始化一次。因为类只加载一次,加载完后创建对象过程中不会再去初始化static部分的东西,所以之后根本不会再走那块初始化代码,又怎么初始化第二次呢?
2、static的优先级是高于main函数执行的,因为它是在类加载时期初始化。当static作用的东西都加载完了才执行main,当然main是第一个被使用的static方法,但是虚拟机只是找到这个方法的位置,并不会先去执行里面的内容。
2、对于类的普通成员属性初始化三个步骤:先全初始化为0,再用申明时候初始化值进行初始化,再调用构造函数进行初始化。
实例程序:(来源于Thinking in Java)
加载类是将所写的程序.java文件编译生成的.class文件加载到内存中,保证了对象创建的预置环境。类加载完毕后才可以创建该类的对象。
第一步:加载类
1. 当开始运行一个类,虚拟机首先试图访问指定启动类的 .main() 方法,加载该类的 .class 文件。
2. 如果该类有父类,那么继续加载其父类,以此类推,直到加载出所有与main入口类相关的类(它的父类,父类的父类等)。
3. 接着,从其顶级父类开始,对其static域按照顺序进行初始化!直至初始化完所有类的static域。>将static域放到静态存储区。
4. 至此类的加载工作完毕了,下面就进入main函数,执行main函数。一般main函数中来创建类的对象,如果发现要创建的类没有被加载,则继续加载该类)
第二步:对象创建
1. 为对象获取内存,然后将内存全部置为0,此时对象中的所有属性都是被赋予0的默认值(内存为0时候的默认值:null-对象引用,0-int,false-boolean...)> 在堆中生成对象所需空间,全部初始化为0,具体成员属性值为堆上对应内存子块--正是因为这种机制,所以java可以保证所有的类对象的属性都会被初始化,但是局部不会被初始化。
这里需要注意的是:一个对象内部组合了另一个对象,那么在堆中其实存的也是一个引用,这个引用指向被组合对象的堆内存地址(另外再创建)。
当引用在内存的二进制数据都为0的时候,他的表现形式是null;当他指向的数据内容内存区数据都是0的时候,他的值为0,"",False等初始标准值。所谓初始化就是修改内存区的二进制数据,因为对象在创建时候第一步就将内存清0,所以保证了所有属性都能至少被初始化为标准初值!
但是局部变量不一样,你不初始化,只是申明,那么开辟的内存区在栈中值会是一个未知数据(一旦使用该引用的话,使用的可能是你没有初始化而瞎几把乱指的地址)所以Java会代码检验的时候发现你使用了未初始化的引用,直接给予不通过,直接杜绝了这种可能性的发生。
综上,Java中使用任何变量或引用,必须初始化,初始化就是将内存中旧的二进制数据要么清0,要么赋予你要赋的值!
2. 从顶级父类开始,按照申明顺序将给顶级父类的非static的成员属性初始化(static的只初始化一次在类加载阶段)> 用属性定义的值覆盖0值。
3. 调用顶级父类的构造函数,如果有成员属性初始化则覆盖前一个申明时初始化值。> 构造函数再次初始化,覆盖前面申明时初始化。
4. 以此类推,将所有的父级(先初始化属性,在调用构造,一层一层的构造完毕) 构造完成
5. 最后,初始化当前类的非static属性,再调用当前类的构造函数,完成所有初始化工作。
注意:
1、类中static部分是发生在类加载时期的,并且只初始化一次。因为类只加载一次,加载完后创建对象过程中不会再去初始化static部分的东西,所以之后根本不会再走那块初始化代码,又怎么初始化第二次呢?
2、static的优先级是高于main函数执行的,因为它是在类加载时期初始化。当static作用的东西都加载完了才执行main,当然main是第一个被使用的static方法,但是虚拟机只是找到这个方法的位置,并不会先去执行里面的内容。
2、对于类的普通成员属性初始化三个步骤:先全初始化为0,再用申明时候初始化值进行初始化,再调用构造函数进行初始化。
实例程序:(来源于Thinking in Java)
//: reusing/Beetle.java // The full process of initialization. import static net.mindview.util.Print.*; class Insect { private int i = 9; protected int j; Insect() { print("i = " + i + ", j = " + j); j = 39; } private static int x1 = printInit("static Insect.x1 initialized"); static int printInit(String s) { print(s); return 47; } } public class Beetle extends Insect { private int k = printInit("Beetle.k initialized"); public Beetle() { print("k = " + k); print("j = " + j); } private static int x2 = printInit("static Beetle.x2 initialized"); public static void main(String[] args) { print("Beetle constructor"); B 4000 eetle b = new Beetle(); } }
/* Output: static Insect.x1 initialized static Beetle.x2 initialized //1.类加载和初始化静态x1,x2:只会初始化一次! Beetle constructor //2.进入main函数 i = 9, j = 0 //3.new Beetle(),先初始化父类>申请父类内存>初始化为0>初始化i=9,j=0>调用Insect()构造函数>输出ij值>初始化j=39 Beetle.k initialized //4.初始化子类>申请子类内存>..>初始化k,输出改行>调用构造Beetle()>输出下面的k,j k = 47 j = 39 *///:~
相关文章推荐
- java 程序加载过程---2-创建类实例对象
- Java_31_面向对象_Java程序运行的内存分析_栈_堆_引用类型的概念_属性_对象的创建和使用
- Java 对象创建的过程和内存的运行机制
- java 程序加载过程---3--类中申明同时申明类的静态对象 创建类的实例 访问类的静态变量 调用类的静态方法 使用反射方法 初始化类的子类对象 直接使用java.exe 调用某个类
- java程序中创建触发器、存储过程等对象
- 关于Java程序中类定义对象的处理,以及类中变量与方法的运行过程
- 黑马程序员_java 程序运行机制及运行过程
- java对象创建过程
- Java:对象创建和初始化过程
- Java:对象创建和初始化过程
- java中的对象创建过程
- SQL2000安装过程中出现“以前进行的程序创建了挂起的文件操作,运行安装程序前,必须重新启动”的解决办法
- java对象的创建过程(摘自《java编程思想》)
- Java小知识 对象创建和初始化过程,堆:栈区别
- SQL Server安装过程中出现“以前的某个安装程序已在安装计算机上创建挂起的文件操作,运行程序前必须重启计算机”错误的解决方法
- Java小知识 对象创建和初始化过程,堆:栈区别
- Java与C++程序在运行时测试对象的类型
- [转]JAVA中对象创建和初始化过程
- JAVA中对象创建和初始化过程
- Java:对象创建和初始化过程