下面是代码:
package packagename;
import java.lang.reflect.Method;
class Super{
static{
System.out.println("Super");
}
public void superMethod(){
}
}
class Sub extends Super{
static{
System.out.println("Sub");
}
public void subMethod(){
}
}
public class Example {
static{
System.out.println("In Example");
}
public static void main(String[] args){
Class myClass = Sub.class;
Method[] methods = myClass.getMethods();
for(Method eachMethod : methods){
System.out.println(eachMethod.getName() + " with " + eachMethod.getParameterCount() + " parameters");
}
}
}
在编译和执行此代码时,
> java Example
,
class Example
得到加载\链接\\初始化。当Java解释器开始解释class Example
的main()
方法时,在计算表达式Sub.class
并分配给Class myClass
变量class Super
&CCD_ 8被加载&已链接,但未初始化。这就是CCD_ 9&不执行class Sub
,如下输出所示。
In Example
subMethod with 0 parameters
superMethod with 0 parameters
wait with 0 parameters
wait with 2 parameters
wait with 1 parameters
equals with 1 parameters
toString with 0 parameters
hashCode with 0 parameters
getClass with 0 parameters
notify with 0 parameters
notifyAll with 0 parameters
我对类Example
、Super
&Sub
?
参见JVMS§5.5
5.5初始化
类或接口的初始化包括执行其类或接口初始化方法(§2.9(
类或接口C只能作为以下结果进行初始化:
Java虚拟机指令new、getstatic、putstatic或invokestatic中任何一条引用C的指令(§new、§getstatic,§putstatic、§invokestatic(的执行。这些指令通过字段引用或方法引用直接或间接引用类或接口。
在执行新指令时,如果引用的类尚未初始化,则对其进行初始化。
在执行getstatic、putstatic或invokestatic指令时,如果声明解析字段或方法的类或接口尚未初始化,则该类或接口将被初始化。
java.lang.invoke.MethodHandle实例的第一次调用,该实例是第2类(REF_getStatic(、第4类(REF_putStatic(、第6类(REF_invokeStatic(或第8类(REF_newInvokeSpecial(的方法句柄解析(§5.4.3.5(的结果。这意味着,当为invokedynamic指令(§invokedynamics(调用引导方法时,引导方法的类被初始化,这是调用站点说明符的连续解析的一部分
调用类库中的某些反射方法(§2.12(,例如,在class类或java.lang.reflect.包中
如果C是一个类,则初始化它的一个子类。
如果C是一个声明非抽象、非静态方法的接口,则是直接或间接实现C的类的初始化。
如果C是一个类,则在Java虚拟机启动时将其指定为初始类(§5.2(
在初始化之前,必须链接类或接口,即验证、准备和可选地解析。
一般来说,行为有规范。如果你想了解细节,你可以考虑先学习《Java®语言规范》和《Java®虚拟机规范》,如果你不理解某个部分,就提出问题,然后指向提出问题的部分。
只有示例被初始化。Class Sub从常量池中检索
Constant pool:
#1 = Methodref #16.#39 // java/lang/Object."<init>":()V
#2 = Class #40 // Sub
以及来自主的相关代码
Code:
stack=4, locals=4, args_size=1
0: ldc_w #2 // class Sub
3: astore_1
4: aload_1
5: invokevirtual #3 // Method java/lang/Class.getMethods:()[Ljava/lang/reflect/Method;
因此,字节码证实了您的观察结果,即Sub没有初始化。执行代码时不需要。