博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java虚拟机:类的初始化
阅读量:2378 次
发布时间:2019-05-10

本文共 2480 字,大约阅读时间需要 8 分钟。

一、 类的初始化是在类加载的最后阶段进行的.对一个进行主动引用时,才会进行此类的初始化,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 修饰的,这个和对类中定义的常量引用时,进行的初始化是不一样的.

转载地址:http://qxlxb.baihongyu.com/

你可能感兴趣的文章
这么多CPU/显卡成就是AMD首创:大写的YES
查看>>
java实现解压缩(Unzip)功能的实现
查看>>
java操作Access *.mdb数据库的实现
查看>>
jdbc连接数据库的代码片段
查看>>
X86汇编:debug命令详解
查看>>
flex(通过URLLoader)与后台jsp进行交互的例子,包括中文乱码的处理
查看>>
Flex HTTPService如何给后台传递参数
查看>>
Flex取得客户端的IP地址
查看>>
不vista下安装oracle10g(r2)注意事项
查看>>
文件列表输出到文件
查看>>
Ubuntu(804) SSH远程管理服务器安装配置
查看>>
android源码
查看>>
使用Hadoop的JAVA API远程访问HDFS
查看>>
Linux下任务调度服务crond使用
查看>>
ZeroMQ的订阅发布(publish-subscribe)模式
查看>>
使用redis存储全球IP库
查看>>
Snappy Java API简介
查看>>
C/C++中正则表达式库RE2的使用
查看>>
HBase Java API(1.2.X)使用简介
查看>>
Java:实现比较接口时,应该全面的进行各种情况的比较
查看>>