Java虚拟机:类的初始化
来源:互联网 发布:中国联合网络通信电话 编辑:程序博客网 时间:2024/06/05 19:01
一、 类的初始化是在类加载的最后阶段进行的.对一个进行主动引用时,才会进行此类的初始化,Java虚拟机规定只有下面四种情况下才会进行类的初始化:
1 当虚拟机执行:new getstatic putstatic invokestatic 四个字节码指令时,才会进行类的初始化.这个四种字节码指令当new一个对象,读取或设置一个静态变量,调用一个静态方法时就会产生.
2.当使用Java.lang.refelect 包进行反射调用是,如果类还没进行初始化,就会先进行初始化.
3.当对子类进行初始化时,如果他的父类还没有进行初始化,那么先对父类进行初始化.
4.Java虚拟机启动时,需要一个主函数,先对主函数类进行初始化.
因此以上四种情况,对一个类的引用称之为主动引用.
二、当对一个类进行被动引用是,虚拟机并不会对类进行初始化,以下是被动引用的情况:
1.在一个子类中进行对父类的静态变量或者静态方法的引用,此时这个子类属于被动引用,并不会对子类进行初始化.
对于静态变量或者静态方法,只有直接定义这个静态变量和静态方法的类才会被初始化.因此通过子类引用父类中定义静态变量或静态方法,只会触发父类的初始化.
如下代码:
public class SuperClass { static{ System.out.println("父类初始化"); } public static int s =1; public static String getString(){ return "10"; }}public class SubClass extends SuperClass{ static { System.out.println("子类进行初始化"); }}public class MainTest { public static void main(String args[]){ System.out.println(SubClass.getString()); }}
执行结果:
父类初始化10
2 在对一个类的常量,也就是有final修饰的变量,进行引用时,并不会对此类进行初始化.常量在编译阶段会存入调用它的类常量池中,本质上没有直接引用到定义该常量的类,因此不会触发定义常量的类的初始化.如下代码:
public class SuperClass { public final static String NAME="name"; static{ System.out.println("父类初始化"); } public static int s =1; public static String getString(){ return "10"; }}public class MainTest { public static void main(String args[]){ // System.out.println(SubClass.getString()); System.out.println(SuperClass.NAME); }}
执行结果:
name
SuperClass 类没有进行初始化,这一点和引用接口中定义的常量是不同的.下面会有讲解.
3.通过数组对一个类进行引用时.
public class MainTest { public static void main(String args[]){ // System.out.println(SubClass.getString()); // System.out.println(SuperClass.NAME); SuperClass[] supe = new SuperClass[10]; }}
这种情况下并不会执行对SuperClass的初始化.
三、接口的初始化
虚拟机对接口的初始化和对类的初始化是有区别的:
类初始化时,需要完成其所有父类的初始化工作,而对于它实现的接口,虚拟机并不要求其父接口全部初始化完成.
只有真正使用到父接口的时候(比如引用接口中的常量,调用接口中定义的方法)才会初始化该接口.
多说一句,使用接口的常量,其实只能在它的具体实现的子类中引用,因为在子接口中是无法使用的. 如下两个父子接口,两个常量s之间并不存在继承关系,两个s是完全不同的.
public interface SuperInterface { int s = 0; public void getString();}public interface SubInterface extends SuperInterface{ int s=1;}public class SubClass implements SubInterface{ @Override public void getString() { System.out.println(SubInterface.s); System.out.println(SuperInterface.s); } public static void main(String args[]){ SubClass s = new SubClass(); s.getString(); }}
执行结果:
SubInterface.s:1SuperInterface.s:0
接口中定义的常量,也就是由final static 修饰的,这个和对类中定义的常量引用时,进行的初始化是不一样的.
- Java虚拟机:类的初始化
- 《深入理解java虚拟机》:类的初始化
- Java虚拟机 类初始化 阶段
- java虚拟机类初始化顺序
- Java虚拟机的加载、连接和初始化
- Java虚拟机的加载、连接和初始化
- 【深入Java虚拟机】之三:类初始化
- 【深入Java虚拟机】之三:类初始化
- 【深入Java虚拟机】之三:类初始化
- 【深入Java虚拟机】之三:类初始化
- 【深入Java虚拟机】之三:类初始化
- 【深入Java虚拟机】之三:类初始化
- 【深入Java虚拟机】之三:类初始化
- 【深入Java虚拟机】之三:类初始化
- 【深入Java虚拟机】之三:类初始化
- 【深入Java虚拟机】之三:类初始化
- 深入理解 Java 虚拟机-类初始化
- 深入java虚拟机(三)--类初始化
- JavaScript父子窗口互传数据
- 隐藏域的作用
- 关于华为code craft比赛算法(遗传算法)
- 在Eclipse中设置自动生成注释
- IReport的用法
- Java虚拟机:类的初始化
- 你不知道的Google Search
- AIDL文件实例解析
- log日志打印封装,并保存到本地文件
- Dubbo分布式服务治理(一)——Dubbo注册中心&&管理平台安装(Linux)
- mongodb数据库集群及sharding分片配置
- 14.9 节练习
- Mysql LAST_INSERT_ID函数
- DataTruncation数据错误