为什么静态块的子类没有得到执行?(why static block in child class does not get executed?)

编程入门 行业动态 更新时间:2024-10-26 10:38:23
为什么静态块的子类没有得到执行?(why static block in child class does not get executed?)

这里是代码

public class ClassResolution { static class Parent { public static String name; static { System.out.println("this is Parent"); name = "Parent"; } } static class Child extends Parent { static { System.out.println("this is Child"); name = "Child"; } } public static void main(String[] args) throws ClassNotFoundException { System.out.println(Child.name); }}

我期望的结果是:

this is Parent this is Child Child

但实际上是:

this is Parent Parent

看来静态块在Child类中没有得到执行,但是为什么? 这是反直觉,不是吗?

补充: 为了使它更清楚,我列出了 2 1分以下:

正如@axtavt所说,根据JLS 12.4.1 ,类Child被加载,但未初始化。 但@Alexei Kaigorodov指出,根据jvms-5.5 ,由于在Child类上执行getstatic指令,类Child应该被初始化。

你怎么看?

supplement2: @Alexei Kaigorodov已经重申了他的想法,所以似乎没有任何分歧。 但我认为阿列克谢凯戈罗多夫的观点是有启发性的,所以我把它留在那里。

谢谢大家。

here is the code

public class ClassResolution { static class Parent { public static String name; static { System.out.println("this is Parent"); name = "Parent"; } } static class Child extends Parent { static { System.out.println("this is Child"); name = "Child"; } } public static void main(String[] args) throws ClassNotFoundException { System.out.println(Child.name); }}

what ouput i expect is:

this is Parent this is Child Child

but actually is:

this is Parent Parent

it seems static block in Child class does not get executed, but why? it's anti-intuition, doesn't it?

supplement: to make it more clear, i list the 2 1 points below:

As @axtavt say, according to JLS 12.4.1, class Child is loaded, but not initialized. But @Alexei Kaigorodov pointed out, according to jvms-5.5, class Child should be initialized, because of the execution of instruction getstatic on Child class.

what do you think?

supplement2: @Alexei Kaigorodov has renewed his mind, so it seems no disagreement left. But I think the point of Alexei Kaigorodov is enlightening, so I left it there.

Thank you, everyone.

最满意答案

来自JLS 12.4.1 :

类或接口类型T将在第一次出现以下任何一项之前立即被初始化:

T是一个类,创建了一个T的实例。 T是一个类,由T声明的静态方法被调用。 由T声明的静态字段被分配。 使用由T声明的静态字段,该字段不是常量变量(§4.12.4)。 T是一个顶级类,并且执行在词汇上嵌套在T中的断言语句(第14.10节)。

正如你所看到的,这些在你的代码中没有发生(请注意,这个name是在Parent声明的,而不是在Child ),因此Child不会被初始化,并且它的静态块也不会被执行。

如果你做了一些事情来触发Child初始化,你会得到一个预期的输出:

new Child(); System.out.println(Child.name);

但是,请注意,静态字段不是继承的,因此Child.name和Parent.name实际上指向相同的字段。 这就是为什么在实践中使用与您的示例类似的代码没有什么意义。

还要注意的是,尽管Child.name实际上引用了Parent.name ,但它仍然被引用为字节码中的Child.name ,因此您的代码会触发加载Child ,但不会触发它的初始化。

From JLS 12.4.1:

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

T is a class and an instance of T is created. T is a class and a static method declared by T is invoked. A static field declared by T is assigned. A static field declared by T is used and the field is not a constant variable (§4.12.4). T is a top-level class, and an assert statement (§14.10) lexically nested within T is executed.

As you can see, nothing of these happens in your code (note that name is declared in Parent, not in Child), therefore Child doesn't get initialized and its static block doesn't get executed.

If you do something to trigger initialization of Child, you'll get an expected output:

new Child(); System.out.println(Child.name);

Note, however, that static fields are not inherited, therefore Child.name and Parent.name actually refer to the same field. That's why it doesn't make much sense to use code similar to your example in practice.

Also note that despite the fact that Child.name actually refers to Parent.name, it's still referenced as Child.name in the bytecode, therefore your code triggers loading of Child, but not its initialization.

更多推荐

本文发布于:2023-07-29 14:09:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1316757.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:子类   静态   static   block   class

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!