java类什么时候初始化?
Java虚拟机规范中并没有进行强制玉树什么情况下需要开始类加载过程。但是对于初始化阶段,虚拟机规范则是严格规定了有且仅有5种情况必须立即对类进行“初始化”(而加载,验证,准备自然需要在此之前开始):
1.遇到new,getstatic,putstatic,或invokestatic这4条字节码指令时,如果类没有进行过初始化,则需要先触发其初始化。生成这四条指令单最常见的Java代码场景是:使用new关键字实例化对象的时候,读取或设置一个类的静态字段(被final修饰,已在变异期把结果放入常量池的静态字段除外)的时候,以及调用一个类的静态方法的时候。
2.使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先出法其初始化。
3.当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先出法其父类的初始化。
4.当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的那个类),虚拟机会先初始化这个主类。
5.当使用JDK1.7的动态语言支持时,如果一个Java.lang.invoke.MethodHandle实例最后的解析结果REF_getStatic,REF_outStatic,REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行过初始化,则需要先触发其初始化。
对于这五种会触发类进行初始化的场景,虚拟机规范中是用来一个很强烈的现定于:“有且仅有”,这5种场景中的行为称为一个类进行主动引用。
看下面的例子:
package logan.classload.study;
public class SuperClass {
static{
System.out.println("SuperClass init!");
}
public static int value=123;
}
package logan.classload.study;
public class SubClass extends SuperClass {
static{
System.out.println("SubClass init!");
}
}
package logan.classload.study;
public class NotInitialization {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(SubClass.value);
}
}
SuperClass init!
123
思考一下输出结果
对于静态字段,只有直接定义这个字段的类才会被初始化,因此通过其子类来引用父类中定义的静态字段,只会触发父类的初始化而不会触发子类的初始化。至于是否要触发子类的加载和验证,在虚拟机规范中并未明确规定。这点取决于虚拟机的具体实现。对于Sun HotSpot来说,可通过-XX:+TraceClassLoading参数观察到此操作会导致子类的加载。
看下面一个例子:
package logan.classload.study;
public class NotInitialization {
public static void main(String[] args) {
// TODO Auto-generated method stub
SuperClass[]sca = new SuperClass[10];
}
}
没有输出
想想输出结果
运行之后发现没有输出,“SuperClass init!”说明没有处罚类SuperClass的初始化。但是这段代码里面出发了另外一个名为“[Llogan.classload.study.SuperClass”的类的初始化阶段,对于用户代码来说这并不是一个合法的类名称,他是一个由虚拟机自动生成的,直接继承与java.lang.Object的子类,创建动作由字节码指令newarray触发。
这个类代表了一个元素类型为logan.classload.SuperClass的一位数组,数组中应有的属性和方法(用户可以直接使用的只有被修饰为public的length属性和clone()方法)都是现在这个类里。
看下面一个例子
package logan.classload.study;
public class ConstClass {
static{
System.out.println("ConstClass init!");
}
public static final String HelloWorld = "hello world";
}
package logan.classload.study;
public class NotInitialization {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(ConstClass.HelloWorld);
}
}
hello world
猜一下输出结果
输出里面没有输出“ConstClass init!”,这是因为虽然在Java源码中引用了ConstClass类中放常量HelloWorld,但是其实在变异阶段通过常量传播优化,已经将此常量的值“hello world”存储到NotInitialization类的常量池中,以后NotInitialization对常量ConstClass.HelloWorld的引用实际都被转化为NotInitialization类对自身常量池的引用了。
也就是说,实际上NotInitialization的Class文件之中并没有ConstClass类的符号引用入口,这两个类在编译成Class之后就不存在任何联系了。
接口的加载过程与类加载过程稍微有一些不同,针对接口需要做一下特殊说明:接口也有初始化过程,这点与类类是一致的。上面的代码都是用静态语句块“static{}”来输出初始化信息的,而接口中不能使用“static{}”语句块,但是编译器仍然会为接口生成“<client>()”类构造器,用于初始化接口中多定义的成员变量。接口与类真正有所区别的是前面讲述的5种“有且仅有”需要开始初始化场景中的第三种:当一个类在初始化时,要求其父类全部都已经初始化过了,但是一个接口在初始化时,并不要求其父类接口全部完成初始化,只有在真正使用到父类接口的时候(如引用接口中定义的常量)才会初始化。
java类什么时候初始化?的更多相关文章
- Java 类成员的初始化顺序
Java 类成员的初始化顺序 前言:开发中碰到一个Java文件中有很多的成员变量,包括静态和非静态的,还有很多的初始化方法,很好奇这些成员的初始化顺序,在这里作个研究. 1 无继承情况下的Jav ...
- Java类的成员初始化顺序
Java类的成员初始化顺序 2017-06-01 代码: public class InitializeSequence { public static void main(String[] args ...
- java类的成员初始化顺序和初始化块知识
java类的成员初始化顺序和初始化块知识 转自:http://blog.csdn.net/lgfeng218/article/details/7606735 属性.方法.构造方法和自由块都是类中的成员 ...
- Java类和对象初始化
类的生命周期: Java类的初始化: 本阶段负责为类变量赋正确的初始值.(类变量即静态变量) Java编译器把所有的类变量初始化语句和静态初始化器通通收集到<clinit>方法中,该方法只 ...
- Java类、实例初始化的顺序
求如下 java 代码的输出?? class T implements Cloneable{ public static int k = 0; public static T t1 = new T(& ...
- java类中元素初始化顺序
结论:对于静态变量.静态初始化块.变量.初始化块.构造器,它们的初始化顺序依次是(静态变量.静态初始化块)>(变量.初始化块)>构造器. public class Test4 { @Tes ...
- Java类与对象初始化的过程(一道经典的面试题)
本文不再以ClassLoader的视角解释这些问题. 首先,Java代码有个特点,就是成员变量可以在前面的方法中使用,在后面定义.这一特性,很多人说Java了不起,可是为什么呢?Java为何能够这样呢 ...
- Java类的变量初始化顺序
大家在去参加面试的时候,经常会遇到这样的考题:给你两个类的代码,它们之间是继承的关系,每个类里只有构造器方法和一些变量,构造器里可能还有一段代码对变量值进行了某种运算,另外还有一些将变量值输出到控制台 ...
- Java 类的成员初始化顺序
做个简单笔录,就当是重温下基础知识. 1.先看代码: package com.test; public class Test { public static void main(String[] ar ...
随机推荐
- GAN基础
Generative Adversarial Networks GAN框架 GAN框架是有两个对象(discriminator,generator)的对抗游戏.generator是一个生成器, ...
- http keep-alive简解
http协议中,客户端发送请求,服务端在接收到请求后,返回所需要的数据后可以关闭连接,这样客户端读取完数据时会返回EOF(-1),表明数据已接受完全 备注:EOF end of file 什么是kee ...
- 暑假集训第一周比赛G题
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=83146#problem/G G - 向 Crawling in process... C ...
- springmvc的优化
二.springmvc的工作机制 在容器初始化时会建立所有url和controller的对应关系,保存到Map<url,controller>中.tomcat启动时会通知spring初始化 ...
- C++的异常捕获
听课笔记: #define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; void fun() { ;// ...
- Flex学习之(JS中调用Flex的方法)
flex端 public function initApp():void { ExternalInterface.addCallback("function1",call ...
- Appium-xpath详解
一.xpath简介 XPath就是XML 路径,练习XPath的使用可以直接使用火狐浏览器 火狐浏览器下载 free bug和free path两个插件. 手机xpath可以自己写,路径关键字选cla ...
- 使用common-dbutils进行dao操作
jar: 先引出database工具类: package cn.itcast.utils; public class Stu { private int id; private String snam ...
- POJ-1741(树分治)
树的点分治 给出详细的讲解!!点这里打开论文-分治算法在树的路径问题中的应用 本题目是他讲的第一个例题: 我的理解:每次都找树的重心,计算以重心为根的子树之间所贡献的答案.不断这样下去:如果这棵树是一 ...
- listen and translation exercise 49
Huh? Appears to Be Universally Understood What's the most universal utterance in languages across th ...