类加载之 <clinit>() 和 <init>()
前序文章:深入理解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 代码块之前就可以了。
类加载之 <clinit>() 和 <init>()的更多相关文章
- clinit和init(转载)
clinit和init(转载) 今天在看深入Java虚拟机的class文件结构时,看到了这么一句话, 可能出现在class文件中的两种编译器产生的方法是:实例初始化方法(名为<init> ...
- java执行顺序之深入理解clinit和init
原文地址:https://blog.csdn.net/qq_36522306/article/details/80582758 前言: 最近研究了深入理解JVM这本书中的知识,对java中各部分执行的 ...
- <clinit>() 和 <init>()
原文:https://www.cnblogs.com/aspirant/p/7200523.html <clinit>() 类构造器方法 在 类初始化阶段 被执行 由编译器自动收集类中的所 ...
- JVM思考-init和clinit区别
JVM思考-init和clinit区别 目录:JVM总括:目录 clinit和init的区别其实也就是Class对象初始化对象初始化的区别,详情看我上一篇博客: JVM总括四-类加载过程.双亲委派模型 ...
- 深入理解jvm--Java中init和clinit区别完全解析(转)
转自:http://blog.csdn.net/u013309870/article/details/72975536 init和clinit区别 ①init和clinit方法执行时机不同 init是 ...
- 深入理解java虚拟机(4)---类加载机制
类加载的过程包括: 加载class到内存,数据校验,转换和解析,初始化,使用using和卸载unloading过程. 除了解析阶段,其他过程的顺序是固定的.解析可以放在初始化之后,目的就是为了支持动态 ...
- JVM总括四-类加载过程、双亲委派模型、对象实例化过程
JVM总括四-类加载过程.双亲委派模型.对象实例化过程 目录:JVM总括:目录 一. 类加载过程 类加载过程就是将.class文件转化为Class对象,类实例化的过程,(User user = new ...
- JVM性能调优(1) —— JVM内存模型和类加载运行机制
一.JVM内存模型 运行一个 Java 应用程序,必须要先安装 JDK 或者 JRE 包.因为 Java 应用在编译后会变成字节码,通过字节码运行在 JVM 中,而 JVM 是 JRE 的核心组成部分 ...
- 深度分析:面试阿里,字节99%会被问到Java类加载机制和类加载器
1. 类加载机制 所谓类加载机制就是JVM虚拟机把Class文件加载到内存,并对数据进行校验,转换解析和初始化,形成虚拟机可以直接使用的Jav类型,即Java.lang.Class. 2. 类加载的过 ...
随机推荐
- 【合集】有标号的DAG图计数(合集)
[合集]有标号的DAG图计数(合集) orz 1tst [题解]有标号的DAG计数1 [题解]有标号的DAG计数2 [题解]有标号的DAG计数3 [题解]有标号的DAG计数4
- $bzoj3872\ [Poi2014]\ Ant\ colony$ 二分+$dp$
正解:二分+$dp$ 解题报告: 传送门$QwQ$ 一年过去了依然没有头绪,,,$gql$的$NOIp$必将惨败了$kk$. 考虑倒推,因为知道知道除数和答案,所以可以推出被除数的范围,然后一路推到叶 ...
- Windows服务器管理--批量管理工具
iis7批量远程控制: 一款电脑远程监控的工具,IIS7远程桌面管理是一款专业的远程桌面连接软件,无需安装.操作简单方便.完美的界面设计.强大的监控功能.稳定的系统平台,满足了用户实现远程桌面连接的需 ...
- 基于Github Pages + docsify,我花了半天就搭建好了个人博客
目录 前言 一些说明 准备工作 上docsify官网看一看 使用docsify命令生成文档站点 部署到Github上 写在最后 前言 "作为一个真正的码农,不能没有自己的个人博客" ...
- ElementUi 两个表格反选
ElementUi 两个表格反选 1.先看看实现的图 表格内容显示 <el-row :gutter="20"> <el-col :span="16&qu ...
- 基于CentOS 7 部署MySQL 5.7的基本操作
关闭selinux # sed -i '/SELINUX/s/enforcing/disabled/' /etc/selinux/config重启后生效# sestatus 修改提示符配置# vi / ...
- js面试题之手写节流函数和防抖函数
函数节流:不断触发一个函数后,执行第一次,只有大于设定的执行周期后才会执行第二次 /* 节流函数:fn:要被节流的函数,delay:规定的时间 */ function throttle(fn,dela ...
- 单机Web后端接口服务压力测试
单机Web后端接口服务压力测试 工具:Apache jmeter 环境:Window 10 语言:Kotlin + java 架构:SpringBoot + + Mysql + redis + Spr ...
- WPF 添加提示动画
下面放一张效果图: 那么具体是怎么实现呢: 前端XAML中: <Image Source="/Images/tips.png" HorizontalAlignment=&qu ...
- 原型,原型链,给予原型和class的继承
学习react的时候遇到了class方式的继承语法,原理和代码的解释很详细,值得一读. 原型每个函数(构造函数)都有一个 prototype 属性,指向该函数(构造函数)的原型对象.实例没有 prot ...