前序文章:深入理解Java类加载

<clinit>()<init>() 区别

一、<clinit>()

Java 类加载的初始化过程中,编译器按语句在源文件中出现的顺序,依次自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并产生 <clinit>() 方法。 如果类中没有静态语句和静态代码块,那可以不生成 ()` 方法。

并且 <clinit>() 不需要显式调用父类(接口除外,接口不需要调用父接口的初始化方法,只有使用到父接口中的静态变量时才需要调用)的初始化方法 <clinit>(),虚拟机会保证在子类的 <clinit>() 方法执行之前,父类的 <clinit>() 方法已经执行完毕。

二、<init>()

对象构造时用以初始化对象的,构造器以及非静态初始化块中的代码。

<clinit>()<init>() 执行顺序

直接看代码

public class Test {
private static Test instance; static {
System.out.println("static开始");
// 下面这句编译器报错,非法向前引用
// System.out.println("x=" + x);
instance = new Test();
System.out.println("static结束");
} public Test() {
System.out.println("构造器开始");
System.out.println("x=" + x + ";y=" + y);
// 构造器可以访问声明于他们后面的静态变量
// 因为静态变量在类加载的准备阶段就已经分配内存并初始化0值了
// 此时 x=0,y=0
x++;
y++;
System.out.println("x=" + x + ";y=" + y);
System.out.println("构造器结束");
} public static int x = 6;
public static int y; public static Test getInstance() {
return instance;
} public static void main(String[] args) {
Test obj = Test.getInstance();
System.out.println("x=" + obj.x);
System.out.println("y=" + obj.y);
}
}

输出信息如下:

static开始
构造器开始
x=0;y=0
x=1;y=1
构造器结束
static结束
x=6
y=1

虚拟机首先执行的是类加载初始化过程中的 <clinit>() 方法,也就是静态变量赋值以及静态代码块中的代码,如果 <clinit>() 方法中触发了对象的初始化,也就是 <init>() 方法,那么会进入执行 <init>() 方法,执行 <init>() 方法完成之后,再回来继续执行 <clinit>() 方法。

上面代码中,先执行 static 代码块,此时调用了构造器,构造器中对类变量 x 和 y 进行加 1 ,之后继续完 static 代码块,接着执行下面的 public static int x = 6; 来重新给类变量 x 赋值为 6,因此,最后输出的是 x=6, y=1。

如果希望输出的是 x=7,y=1,很简单,将语句 public static int x = 6; 移至 static 代码块之前就可以了。

最新文章

  1. .net线程池内幕
  2. POJ 1780 Code(有向图的欧拉通路)
  3. [译]Mongoose指南 - Population
  4. java 缩略图
  5. EXCEL工作表保护密码忘记了,如何撤消工作表保护?
  6. ACM题目————Team Queue
  7. Codeforces Round #373 (Div. 2) A
  8. mysql存储过程和事件
  9. UBUNTU 14.04 + CUDA 7.5 + CAFFE
  10. Swift下标
  11. Modules you should know in Python Libray
  12. Web---Cookie技术(显示用户上次登录的时间、显示用户最近浏览的若干个图片(按比例缩放))
  13. JAVA文件名命名规范
  14. 三、VueJs 填坑日记之项目文件认识
  15. canvas绘制圆心扇形可组成颜色随机的七色小花
  16. 动手写 js 沙箱
  17. redis整合Spring集群搭建及业务中的使用
  18. Google API Design Guide (谷歌API设计指南)中文版
  19. JavaScript跨域解决方式
  20. suse11安装mysql5.7

热门文章

  1. MyBatis学习与使用(一)
  2. 给你的 ASP.NET Core 程序插上 Feature Flag 的翅膀
  3. $[SHOI2007]$ 园丁的烦恼 二维数点/树状数组
  4. @Configuration结合@Bean实现对象的配置
  5. json查询结果绑定
  6. 在GeneXus开发过程中如何进行自动化测试?
  7. FNScanner二维码接口openView自定义扫码Demo
  8. 1z0-062 题库解析6
  9. selenium webdriver从安装到使用(python语言),显示等待和隐性等待用法,切换窗口或者frame,弹框处理,下拉菜单处理,模拟鼠标键盘操作等
  10. 如何利用Serilog的RequestLogging来精简ASP.NET Core的日志输出