一道关于类初始化的面试题

什么叫做主动引用?


1:遇到new、getstatic、putstatic、或者invokestatic这4条字节码指令时候,如果类没有进行过初始化,则需要先进行初始化。生成4条字节码指令的最常见的Java代码场景是:使用new关键字实例化对象的时候、读取或者设置一个类的静态字段(被final修饰、已在编译期间把结果放入常量池的静态字段除外)的时候,以及调用一个类的静态方法的时候。

2:使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行初始化,则需要县触发其初始化。

3:当初始化一个类的时候,如果发现其父类还没有过初始化,则需要先触发其福利的初始化。

4:当虚拟机启动时,用户需要制定一个要执行的主类(包含main()方法的那个类),虚拟机辉县初始化这个类

5:当使用jdk1.7的动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getstatic、REF_putstatic、REF_invokestatic的方法句柄,并且这个方法句柄锁对应的类没有进行过初始化,则需要先触发其初始化。

对于上面这5种会出发类进行初始化的场景我们称之为主动应用

除此之外,所有引用类的方式都不会触发初始化,称之为被动引用

上面的答案是只会输出


而不会输出"子类静态模块"

对于静态字段,只有直接定义这个字段的类才会被初始化,因此通过其子类来引用父类中定义的静态字段,只会出发父类的初始化而不会出发子类的初始化。

如果把SuperClass中常量改成字符串常量   


运行结果:


这是因为在编译期间通过常量传播优化,已经将此常量得知“hello world”存贮到了TestSubAndSuperClass类的常量池中,以后TestSubAndSuperClass对常量的引用实际都是被转化为TestSubAndSuperClass类对资深常量池的引用了,也就是说实际上TestSubAndSuperClass的class文件中并没有SuperClass类的符号引用入口,这两个类在编译成Class文件之后就没有任何关联了。


猜你喜欢

转载自blog.51cto.com/10983206/2563887
今日推荐