实例化一个对象(类加载)的执行顺序详解
来源:互联网 发布:淘宝泳衣买家秀 编辑:程序博客网 时间:2024/05/16 04:56
这篇博客将以类加载执行顺序为探索的起点,串讲涉及到的Java相关知识,主要是这个流程中JVN内部运行机制的解析。
结论
注解:
默认该类及其父类JVM未曾加载过
先父后子,先静后常再构造
同等级内代码逐条按顺序执行
* 当静态代码和非静态代码中成员变量包含对象,也会先执行该对象类的静态代码和构造函数
先修知识
JVN 运行时数据区
JVN内存可简单分为三个区:堆(heap)、栈(stack)和方法区(method):
堆区
存放对象本身(包括非static成员变量),所有线程共享栈区
存放基础数据类型、对象的引用,每个线程独立空间,不可互相访问
栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)- 方法区(静态区,包含常量池)
存永远唯一元素(类-class、类变量-static变量、方法),所有线程共享
实例化一个对象的执行顺序分析
因为涉及到的情况可以很复杂,最复杂的情况可能是有多个父类,父类及子类中有多个成员变量对象,这种情况下调用栈会比较深,所以我们先重简单一个单独的类开始分析,而且只要明白了基础的过程,那么再复杂的情况也只是在这个基础上叠加调用。
一个单独的类的情况
有父类存在的情况
有父才有子,所以当父类存在时(其实Object类是所有类的父类),只是在这两个阶段前(执行静态、执行非静态)前,先运行父类的相关代码
默认该类及其父类JVM未曾加载过
此处为什么要执行父类的构造方法呢?(此处存疑,待查证,欢迎指正)
因为子类的构造方法默认调用super();
创建子类实例的时,如果没有super调用父类带参数的构造方法,则默认会调用父类的无参构造方法,默认调用super().
当类中包含属性类时
因为同等级内代码逐条按顺序执行,所以当存在属性类时,例如:
public class A { static { System.out.println("A static"); } B b = new B(); { System.out.println("A not static"); } A(){ System.out.println("A constructor"); } public static void main(String[] args) { System.out.println("Hello World!"); A m = new A(); }}class B{ static { System.out.println("B static"); } { System.out.println("B not static"); } B(){ System.out.println("B constructor"); }}
结果输出如下:
A staticHello World!B staticB not staticB constructorA not staticA constructor
在实例化A类时,在顺序执行到非静态代码中的“B b = new B()”时,将先执行加载完毕B的所有代码;
如果我将代码改成“非静态代码块”在“实例化B代码”前,如下:
... { System.out.println("A not static"); } B b = new B();...
将会得到如下输出
A staticHello World!A not static//这一行也在前面了B staticB not staticB constructorA constructor
得以验证:同等级内代码逐条按顺序执行,遇到属性类则加载完属性类后再执行下一步代码
注意:当属性类不立刻进行实例化时,JVM只会将堆中的成员属性类指向一个null,而不进行加载该属性类的操作
例:
... B b;...
代码如上时,将不会有任何与类B相关的输出
关联知识
类变量-static变量、类方法-static方法
这两者的特性:
- 全局唯一,一改都改,节省资源
- 可直接通过类名调用
- 仅能访问static数据、static方法
- 不能引用this和super
下面我们通过实例化对象执行步骤来推导出以上四条特性:
由流程图可知,
1. static代码只在类初始化时加载一次,加载后存在方法区,而每一个对象在实例化时,只是在堆中保存指向方法区的引用,所以全局唯一,一改都改,节省资源
2. 因为static代码在对象被实例化之前和类初始化一起执行,所以除了可以通过对象应用外,也可以直接通过类名引用
3. 因为先执行静态代码,再执行非静态代码,所以static代码仅能访问static数据、static方法
4. this、super属于非静态代码(??),所以不能引用this和super
- 实例化一个对象(类加载)的执行顺序详解
- 实例化一个类的对象时的执行顺序
- 类从加载到对象实例化的过程顺序
- 黑马程序员-实例化对象执行时的执行顺序
- Unity对象实例的执行顺序探究及一个对象关联多个脚本的
- 类的加载、实例化、初始化的区别和执行顺序
- Java实例化对象时候的加载顺序
- 实例化类的执行顺序
- 类的加载、执行顺序
- java类的初始化块/执行顺序,实例化对象数据赋值
- java 类的实例 new一个对象初始化顺序
- java 类的实例 new一个对象初始化顺序
- java类加载和实例化:静态代码块、初始化代码块、构造方法的执行顺序
- 加载顺序,一个类的
- 类的加载顺序(详解)
- Java中类加载的执行顺序
- java类的执行顺序、语句执行顺序详解
- Java类实例化时的执行顺序
- bzoj2460 [ Beijing2011 ] -- 线性基+贪心
- Linq常用List操作总结,Foreach、分页、交并集、去重、SelectMany等
- Linux命令大全完整版
- 【Java设计模式】简单工厂模式
- Java高并发,如何解决,什么方式解决
- 实例化一个对象(类加载)的执行顺序详解
- 安装libstdc++.so.6
- 汽车保险一年不少钱呀
- POJ-1312 棋盘问题
- 文章标题
- jdbcType与javaType的对应关系
- unity学习日记:Ray(射线)相关知识
- Android studio中为项目添加模块依赖的过程
- 【android】开发干货-图片合成之生成《飞行员驾驶证》