资讯专栏INFORMATION COLUMN

总结一个某东的面试题 --- java类的初始化时机

Vixb / 1533人阅读

摘要:今天去某东面试一个特基础特简单的问题竟然一不小心脑子短路给答错了,太懊恼了,记下以至警告问题如下现有基类,的构造函数中输出,中有一静态块内输出,的一个派生类的构造函数中输出类中的静态块中输出。

今天去某东面试一个特基础特简单的问题竟然一不小心脑子短路给答错了,太懊恼了,记下以至警告:

问题如下:

现有基类A,A的构造函数中输出“A Instance”,A中有一静态块内输出“A init”,A的一个派生类B的构造函数中输出“B instance”, B类中的静态块中输出“B init”。问:A a = new B(); 输出结果及正确的顺序?
public class A{
    static{
        System.out.println("A init");
    }
    public A(){
        System.out.println("A Instance");
    }
}

public class B extends A{
    static{
        System.out.println("B init");
    }
    public B(){
        System.out.println("B Instance");
    }
}

如果是这样呢:A[] sca = new B[10]; 这是什么也不会输出的。

总结一些其他的情况:

public class SuperClass{
    static{
        System.out.println("SuperClass init");
    }
    
    public static int value = 123;
}
public class SubClass extends SuperClass{
    static{
        System.out.println("SubClass init");
    }
    
    public static final String HELLOWORD = "hellow word";
}

public class NotInitialization{
    public static void main(String[] args){
        
        /**
        * 这里只会输出“SuperClass init”, 而不会输出“SubClass init”. 
        * 对于静态字段,只有直接定义这个字段的类才会被初始化
        * 因此通过子类引用父类中定义的静态字段,只会触发父类的初始化不会触发子类的初始化   
        */
        System.out.println(SubClass.value);
        
        /*
        * 这里也不会输出“SubClass init”, 
        * 这里因为虽然在Java源代码中引用了SubClass类中的常量HELLOWORD, 
        * 但是在编译阶段通过常量传播优化,
        * 已经将此常量的值“hellow word”放到了NotInitialization类的常量池中,
        * 以后NotInitialization对常量 SubClass.HELLWORD 的引用实际都被转化为NotInitialization类对自身常量池的引用了
        */
        System.out.println(SubClass.HELLOWORD);
    
    }
}

总结:

对于类的初始化虚拟机规范中明确指出有且只有一下五中情况会立即执行对类的初始化:
1、遇到 new、getstatic、putstatic或invokestatic 着四条指令时,这四条指令分别代表:
    使用new关键字实例化对象、读取或设置静态字段、调用一个类的静态方法。
    
2、使用jav.lang.reflect包中的方法对类进行反射调用。

3、当初始化一个类的时候,如果该类的父类没有初始化,则需要先初始化起父类

4、当虚拟机启动时,用户需要指定一个要执行的主类(包括main()方法的那个类),虚拟机会先初始化这个主类

5、使用jdk1.7的动态语言支持时,如果一个java.lang.MethodHandle实例最后的解析结果是:REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,且这个方法句柄所对应的类没有初始化则需要先触发其初始化

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/64895.html

相关文章

  • JAVA面试(45)

    摘要:本文首发于的博客转载请注明出处与的区别作用对象是类的静态方法,作用于当前线程是类的成员方法,作用于对象本身作用调用方法,线程进入休眠状态调用方法,线程进入阻塞状态锁的释放不会释放持有的锁会释放锁唤醒自然唤醒或者显式调用方法调用或者方法调用不     本文首发于cartoon的博客    转载请注明出处:https://cartoonyu.github.io/c... java sl...

    Allen 评论0 收藏0
  • 类的加载机制,双亲委派模型,搞定大厂高频面试

    摘要:验证验证是连接阶段的第一步,这一阶段的目的是为了确保文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。字节码验证通过数据流和控制流分析,确定程序语义是合法的符合逻辑的。 看过这篇文章,大厂面试你「双亲委派模型」,硬气的说一句,你怕啥? 读该文章姿势 打开手头的 IDE,按照文章内容及思路进行代码跟踪与思考 手头没有 IDE,先收藏,回头看 (万一哪次面试问...

    Object 评论0 收藏0
  • 金三银四,2019大厂Android高级工程师面试整理

    摘要:原文地址游客前言金三银四,很多同学心里大概都准备着年后找工作或者跳槽。最近有很多同学都在交流群里求大厂面试题。 最近整理了一波面试题,包括安卓JAVA方面的,目前大厂还是以安卓源码,算法,以及数据结构为主,有一些中小型公司也会问到混合开发的知识,至于我为什么倾向于混合开发,我的一句话就是走上编程之路,将来你要学不仅仅是这些,丰富自己方能与世接轨,做好全栈的装备。 原文地址:游客kutd...

    tracymac7 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<