java 中的静态变量,静态代码块,动态代码块,构造方法执行顺序的深入探究
要想完全弄懂这个执行顺序,需要我们先了解几个概念。
首先是类加载与对象的构造,类加载就是在第一次调用这个类的时候jvm虚拟机会通过类加载器在一个叫做方法区的逻辑内存中将所要用到的类的信息存放在里边,其中方法区有一个静态区,存放的是类中的静态(类变量),而对象构造则只是在堆中开辟一个内存空间将实例化的对象存放在里边,在生命周期中要远远小于类。
第二是java中关于静态代码块与动态代码块的注释,静态代码块只有在类加载时仅且执行一次,而动态代码块是在每次构造对象时执行一次,然后才是构造方法,也就有了一个顺序,静态代码块>动态代码块>构造方法,而静态变量与静态代码块的优先级是一个级别的,这样看来好像问题解决了,但其实问题并不是这么简单。
接下来还是找一个有说服力的例子,阿里巴巴的一道面试题。
//package com.basics.day09;public class Test {public static int k = 0;public static Test t1 = new Test("t1");public static Test t2 = new Test("t2");public static int i = print("i");public static int n = 99;private int a = 0;public int j = print("j");{print("构造块");}static {print("静态块");}public Test(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[]) {Test t = new Test("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
这样的结果是不是与我们所想的不一样,按照上边的那个顺序,应该是先静态变量,然后是静态代码块,然后是动态代码块,最后才是构造函数,可是上边的结果,很明显是先执行的非静态的赋值变量,然后动态代码块,然后构造方法,静态代码块一次都没有执行,一直等到第八次才执行出来。
那么问题就来了,java中不是说静态代码块是在类加载时便执行一次,可是这里为什么不执行。
解答这个问题还得在看一段代码:
package com.basics.day10;public class TestStatic {static {System.out.println("这时TestStatic的静态代码块!");}{System.out.println("这是动态代码块!");}public TestStatic() {System.out.println("这是构造代码块");}public static void main(String[] args) {TestStatic te = new TestStatic();TestStatic t2 = new TestStatic();}}
// 请注意看这个类中的静态代码块
class Annoy {static {System.out.println("Annoy的静态代码块");}
}
执行结果:
这时TestStatic的静态代码块!
这是动态代码块!
这是构造代码块
这是动态代码块!
这是构造代码块
这个结果是不是就与我们所理解的一样,但是重点不是在这里,重点是我们声明的第二类Annoy,里边的静态代码块没有被执行,这是为什么呢???
呵呵,这还是类加载的问题,因为我们在主类中并没有引用这个类,也就是这个类并没有被加载进方法区,既然它没有被加载,那么其中的代码块自然就不会执行了。
这里有一个很重要的概念,就是类的加载只有在引用它的时候才会加载,而不是直接加载进方法区的,这也是类加载与构造对象的区别。构造对象并不是类加载,它们是两个完全不一样的概念,类加载要在对象构造之前。
到了这里,我们折回到阿里巴巴的那道题中,发现他在第二行的时候进行了对象的构造,而在这个构造中执行的都是非静态的代码块。我是这样理解的,在这个类的main函数被jvm识别的时候,这个类已经加载到方法区中去了,这时候静态都会被执行一次,而且是按照声明的顺序执行的,正常下来,先k,t1,t2...跳过j,到静态代码块,但这里t1有了一个变故,那就是他构造了一个对象,这时类已经加载完成,相当于静态已经默认被执行了一次,只是顺序上还没有轮到,根据静态的特性,他只执行一次,所以t1这里的分支,调用的就是动态代码块以及构造方法,不会去管那些静态,这也就导致出现了上边的那种情况。
到此,这个问题就解决完成了。
java 中的静态变量,静态代码块,动态代码块,构造方法执行顺序的深入探究相关推荐
- php载入内存的是本地代码吗,常量和静态变量会先载入内存后在进行执行php代码...
static $test=1;//在php执行前就已经写入内存 $test++; var_dump($test); static $test=10;//在php执行前就已经写入内存 var_dump( ...
- java中cbrt_Java Math类静态double cbrt(double d)示例
java中cbrt 数学类静态double cbrt(double d) (Math Class static double cbrt(double d)) This method is availa ...
- java中为final变量赋值的几种方式
java中为final变量赋值的几种方式 前言 使用final修饰变量,很多人第一时间想到的就是不可变.然后以为变量必须得在声明的时候就为其赋初始值,其实不然,本文将详细讲解java中使用final修 ...
- 【Groovy】Groovy 动态语言特性 ( Groovy 中的变量自动类型推断以及动态调用 | Java 中必须为变量指定其类型 )
文章目录 前言 一.Groovy 动态语言 二.Groovy 中的变量自动类型推断及动态调用 三.Java 中必须为变量指定其类型 前言 Groovy 是动态语言 , Java 是静态语言 ; 一.G ...
- java中的实例变量
简介 在类的声明中,属性是用变量来表示的.这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的.类的每个对象维护它自己的一份实例变量的副本. java中的实例变量 含义: 实例变量 ...
- Java中的宏变量,宏替换详解。
转载自 Java中的宏变量,宏替换详解. 群友在微信群讨论的一个话题,有点意思,特拿出来分享一下. 输出true false 来看下面这段程序,和群友分享的大致一样. public static vo ...
- final变量存在哪 java_使用Java中的final变量需要注意的地方。
对与java中的final变量,java编译器是进行了优化的.每个使用了final类型变量的地方都不会通过连接而进行访问.比如说Test类中使用了Data类中一个final的int数字fNumber= ...
- 继承中的构造方法执行顺序
继承中的构造方法执行顺序 在子父类中,创建子类对象,调用子类的构造方法, 在子类的构造方法的第一行代码如果没有调用父类的构造或者没有调用子类的其他构造,则默认调用父类无参构造. 为什么要调用父类构造? ...
- java静态/动态成员变量、初始化块,父类/子类构造函数执行顺序问题
2019独角兽企业重金招聘Python工程师标准>>> /* * 几大原则 * 一.静态成员变量(Static) * 1.静态成员变量为类变量,所有对象共享同一内存空间 * 2.静态 ...
最新文章
- mysql外键约束视频教学_外键约束案例_MySQL数据库 快速入门 基础+实战 视频教程_MySQL视频-51CTO学院...
- python适合零基础学习吗-零基础,经济学专业,适合自学Python吗?
- 006_P名称空间的属性注入
- JVM--对象的实例化过程
- Cisco 3550-EMI 交 换 机 配 置 教 程
- 移动应用安全形势分析报告
- Nginx开启stub_status模块配置方法_nginx
- 【案例讨论】从案例引发的对缓存设计的思考,干货讨论,绝对不玩虚的
- 前端项目引入js文件写绝对目录还是相对目录_flask入门(三)静态文件
- Java对MongoDb的CURD操作
- Oralce/MySQL 默认隔离级别对比
- 解决UITableView分割线距左边有距离的办法
- mysql 小辉_小辉-MySQL数据库教程 完整高清版40集全!(主流)
- 人脸对齐中的相似性变换
- 实验三 译码器及其应用
- ps用画笔工具设计水墨圆环
- 【Javascript 基础】课堂笔记1
- 令人生畏的源码,到底该怎样看?
- python批量修改文件扩展名
- 皕杰报表自定义扩展~自定义数据集