转自:http://blog.csdn.net/u013309870/article/details/72975536

init和clinit区别

①init和clinit方法执行时机不同

init是对象构造器方法,也就是说在程序执行 new 一个对象调用该对象类的 constructor 方法时才会执行init方法,而clinit是类构造器方法,也就是在jvm进行类加载—–验证—-解析—–初始化,中的初始化阶段jvm会调用clinit方法。


②init和clinit方法执行目的不同

init is the (or one of the) constructor(s) for the instance, and non-static field initialization. 
clinit are the static initialization blocks for the class, and static field initialization. 
上面这两句是Stack Overflow上的解析,很清楚init是instance实例构造器,对非静态变量解析初始化,而clinit是class类构造器对静态变量,静态代码块进行初始化。看看下面的这段程序就很清楚了。

class X {

   static Log log = LogFactory.getLog(); // <clinit>

   private int x = 1;   // <init>

   X(){
// <init>
} static {
// <clinit>
} }

1

  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

clinit详解

在准备阶段,变量已经赋过一次系统要求的初始值,而在初始化阶段,则根据程序员通过程序制定的主观计划去初始化类变量和其他资源,或者可以从另外一个角度来表达:初始化阶段是执行类构造器<clinit>()方法的过程。


①<clinit>()方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块(static{}块)中的语句合并产生的,编译器收集的顺序是由语句在源文件中出现的顺序所决定的,静态语句块中只能访问到定义在静态语句块之前的变量,定义在它之后的变量,在前面的静态语句块可以赋值,但是不能访问如下代码

public class Test{
static{
i=0;//给变量赋值可以正常编译通过
System.out.print(i);//这句编译器会提示"非法向前引用"
}
static int i=1;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

虚拟机会保证在子类的<clinit>()方法执行之前,父类的<clinit>()方法已经执行完毕。 因此在虚拟机中第一个被执行的<clinit>()方法的类肯定是Java.lang.Object。由于父类的<clinit>()方法先执行,也就意味着父类中定义的静态语句块要优先于子类的变量赋值操作,如下代码中,字段B的值将会是2而不是1。

static class Parent{
public static int A=1;
static{
A=2;}
static class Sub extends Parent{
public static int B=A;
}
public static void main(String[]args){
System.out.println(Sub.B);
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

接口中不能使用静态语句块,但仍然有变量初始化的赋值操作,因此接口与类一样都会生成<clinit>()方法。 但接口与类不同的是,执行接口的<clinit>()方法不需要先执行父接口的<clinit>()方法。 只有当父接口中定义的变量使用时,父接口才会初始化。 另外,接口的实现类在初始化时也一样不会执行接口的<clinit>()方法。 
注意:接口中的属性都是static final类型的常量,因此在准备阶段就已经初始化话。

 

深入理解jvm--Java中init和clinit区别完全解析(转)的更多相关文章

  1. JVM思考-init和clinit区别

    JVM思考-init和clinit区别 目录:JVM总括:目录 clinit和init的区别其实也就是Class对象初始化对象初始化的区别,详情看我上一篇博客: JVM总括四-类加载过程.双亲委派模型 ...

  2. java中ArrayList 、LinkList区别

    转自:http://blog.csdn.net/wuchuanpingstone/article/details/6678653 个人建议:以下这篇文章,是从例子说明的方式,解释ArrayList.L ...

  3. java 中 ==和equals 的区别

      Java中equals和==的区别 java中的数据类型,可分为两类: 1.基本数据类型,也称原始数据类型.byte,short,char,int,long,float,double,boolea ...

  4. java中equals和==的区别 (转)

    java中equals和==的区别  值类型是存储在内存中的堆栈(以后简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中. ==操作比较的是两个变量的值是否相等,对于引 ...

  5. 【转】Java中equals和==的区别

    [转]Java中equals和==的区别 java中的数据类型,可分为两类: 1.基本数据类型,也称原始数据类型.byte,short,char,int,long,float,double,boole ...

  6. java中a++与++a区别

    java中a++与++a区别 a++与++a的区别,如果单独使用没有任何区别,如果在运算中就有区别了,a++是先运算在赋值,而++a是先赋值在运算!! 先看a++的代码哦 class demo1 { ...

  7. c#与java中byte字节的区别及转换方法

    原文:c#与java中byte字节的区别及转换方法 在java中  byte的范围在 [-128,127] 在C#中  byte的范围在 [0,255] 所以 java程序与C#程序 进行数据传输的时 ...

  8. java中==与equel的区别

    值类型是存储在内存中的堆栈(以后简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中. ==操作比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量在堆中存储的地 ...

  9. Java中的“&”和“&&”的区别

    Java中的"&"和"&&"的区别 1."&"是位运算符,"&&"是逻辑 ...

随机推荐

  1. ajax返回值传给js全局变量

    1. $.ajaxSetup({ async : false //设置ajax为同步方式,异步方式的话在赋值时数据还未提取出来 });var t = ""; var enginee ...

  2. android编译make错误——"javalib.jar invalid header field”、"classes-full-debug.jar 错误 41 "

    错误:读取 out/target/common/obj/JAVA_LIBRARIES/core-tests_intermediates/javalib.jar 时出错:invalid header f ...

  3. x64dbg使用心得

    使用ScyllaHide插件时 注意一下事项 xdbg64设置里启动 附加必须第一次断下在 系统断点 然后再启用ScyllaHide. 停止调试 脱离时.必须关闭ScyllaHide 否则会报异常 x ...

  4. django restframwork教程之Request和Response

    从这一篇文章开始,我们会覆盖整个REST framwork框架的核心,接下来让我们介绍一些基础的构建块 Request 对象 REST framework 引入了一个扩展HttpRequest的请求对 ...

  5. PHP的函数-----生成随机数、日期时间函数

    常用的函数 [1]   生成随机数 rand(); 例子: echo rand(); 显示结果: 当刷新时,会有不同的数,默认生成随机数.生成随机数不能控制范围. 如果,想要控制在范围之内,就用: e ...

  6. zabbix修改和查看登录密码

    author:hendsen chen date : 2018-08-30  16:48:18 1,登陆zabbix的服务器,查看zabbix的登陆密码: [root@jason ~]# mysql ...

  7. 【BZOJ1834】[ZJOI2010]network 网络扩容 最大流+最小费用流

    [BZOJ1834][ZJOI2010]network 网络扩容 Description 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1. 在不 ...

  8. 【BZOJ1500】[NOI2005]维修数列 Splay

    [BZOJ1500][NOI2005]维修数列 Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行 ...

  9. 香港主机Squid+Stunnel代理搭建

    1.说明 Squid,代理软件 Stunnel,数据包加密(貌似如果数据不加密,客户端的数据流无法传到squid服务端,原因你懂的!) 2.Squid安装略 3.安装完squid后需要以下操作 a.生 ...

  10. redis link 链表结构

    lpush key value 作用: 把值插入到链接头部 rpop key 作用: 返回并删除链表尾元素 lrange key start stop 作用: 返回链表中[start ,stop]中的 ...