继承中的静态方法
Static method in inheritance
class A
{
static{
get();
}
static void get(){
System.out.println("HELLO");
}
}
class B extends A
{
public static void main(String[] args) {
}
}
输出:
HELLO
如何调用 class A
的静态方法。我可以理解 B
的静态方法被调用但不理解 A
.
因为,由于B
继承了A
,B
在main()
执行时,必须加载A
。这将激活 get()
函数,因为它位于静态块中。
因为 B 从 A 扩展,如果 B class 被加载,那么 A class 必须被加载,如果它被加载,它的静态初始化块必须被调用。
在继承中 class 加载是从上到下发生的,即父到子。
它首先在您的案例 A
中加载父项 class,然后在您的案例 B
中加载子项 class。当 class 加载它的静态块时首先被调用,这就是为什么它的打印 HELLO
在编译期间,编译器知道 B 依赖于 A。它将相同的数据传递给 JVM。在class B的加载阶段,JVM读取编译器发送的元数据,发现B
依赖于A
,因此加载(和 A
的 运行s 静态初始化程序)然后继续加载 B
然后初始化 B
。
如果我们有 2 classes Sample
和 Test extends Sample
,Class 常量池(字节码的一部分)对于 Test
将有:
Constant pool:
#1 = Class #2 // Test
#2 = Utf8 Test
#3 = Class #4 // Sample <---- reference
#4 = Utf8 Sample
#5 = Utf8 <init>
#6 = Utf8 ()V
#7 = Utf8 Code
#8 = Methodref #3.#9 // Sample."<init>":()V <-- init Sample
#9 = NameAndType #5:#6 // "<init>":()V
#10 = Utf8 LineNumberTable
#11 = Utf8 LocalVariableTable
#12 = Utf8 this
#13 = Utf8 LTest;
#14 = Utf8 main
#15 = Utf8 ([Ljava/lang/String;)V
#16 = Utf8 args
#17 = Utf8 [Ljava/lang/String;
#18 = Utf8 SourceFile
#19 = Utf8 Sample.java
如果你 运行 java 使用 verbose:class
选项然后 grep 它,你将能够看到 dependant class 正在加载。
java -verbose:class Test | grep 'Sample'
[Loaded Sample from file:/Users/XXXX/Workspaces/SampleTest/Sample/bin/] <== Sample loaded first because test depends on Sample.
[Loaded Test from file:/Users/XXXX/Workspaces/SampleTest/Sample/bin/]
要执行classB的main方法,必须加载classB。
Class B extends class A,所以要加载B,必须加载class A。
当 class A 被加载时,它的静态初始化器被调用,调用 get() 方法并打印 "HELLO".
所有静态块都在 class 加载时执行...重复问题 When is the static block of a class executed?
class A
{
static{
get();
}
static void get(){
System.out.println("HELLO");
}
}
class B extends A
{
public static void main(String[] args) {
}
}
输出:
HELLO
如何调用 class A
的静态方法。我可以理解 B
的静态方法被调用但不理解 A
.
因为,由于B
继承了A
,B
在main()
执行时,必须加载A
。这将激活 get()
函数,因为它位于静态块中。
因为 B 从 A 扩展,如果 B class 被加载,那么 A class 必须被加载,如果它被加载,它的静态初始化块必须被调用。
在继承中 class 加载是从上到下发生的,即父到子。
它首先在您的案例 A
中加载父项 class,然后在您的案例 B
中加载子项 class。当 class 加载它的静态块时首先被调用,这就是为什么它的打印 HELLO
在编译期间,编译器知道 B 依赖于 A。它将相同的数据传递给 JVM。在class B的加载阶段,JVM读取编译器发送的元数据,发现B
依赖于A
,因此加载(和 A
的 运行s 静态初始化程序)然后继续加载 B
然后初始化 B
。
如果我们有 2 classes Sample
和 Test extends Sample
,Class 常量池(字节码的一部分)对于 Test
将有:
Constant pool:
#1 = Class #2 // Test
#2 = Utf8 Test
#3 = Class #4 // Sample <---- reference
#4 = Utf8 Sample
#5 = Utf8 <init>
#6 = Utf8 ()V
#7 = Utf8 Code
#8 = Methodref #3.#9 // Sample."<init>":()V <-- init Sample
#9 = NameAndType #5:#6 // "<init>":()V
#10 = Utf8 LineNumberTable
#11 = Utf8 LocalVariableTable
#12 = Utf8 this
#13 = Utf8 LTest;
#14 = Utf8 main
#15 = Utf8 ([Ljava/lang/String;)V
#16 = Utf8 args
#17 = Utf8 [Ljava/lang/String;
#18 = Utf8 SourceFile
#19 = Utf8 Sample.java
如果你 运行 java 使用 verbose:class
选项然后 grep 它,你将能够看到 dependant class 正在加载。
java -verbose:class Test | grep 'Sample'
[Loaded Sample from file:/Users/XXXX/Workspaces/SampleTest/Sample/bin/] <== Sample loaded first because test depends on Sample.
[Loaded Test from file:/Users/XXXX/Workspaces/SampleTest/Sample/bin/]
要执行classB的main方法,必须加载classB。
Class B extends class A,所以要加载B,必须加载class A。
当 class A 被加载时,它的静态初始化器被调用,调用 get() 方法并打印 "HELLO".
所有静态块都在 class 加载时执行...重复问题 When is the static block of a class executed?