当前位置: 首页 > 面试题库 >

为什么子类中的静态块无法执行?

李永寿
2023-03-14
问题内容

这是代码

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 分:

  1. 正如@axtavt所说,根据JLS 12.4.1,类Child已加载,但未初始化。
  2. 但是@Alexei Kaigorodov指出,根据 jvms-5.5,应初始化Child类,因为对Child类执行了getstatic指令。

你怎么看?

补充2:
@Alexei Kaigorodov更新了主意,因此似乎没有分歧。但是我认为阿列克谢·凯戈罗多夫(Alexei
Kaigorodov)的观点很有启发性,所以我把它留在那里。

谢谢大家。


问题答案:

从JLS
12.4.1开始

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

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

如您所见,这些都不会在您的代码中发生任何变化(请注意,该name声明是在Parent中而不是在中声明的Child),因此Child不会被初始化,并且其静态块也不会被执行。

如果您执行一些操作来触发的初始化Child,则会得到预期的输出:

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

但是请注意,该静态字段不能被继承,因此Child.nameParent.name实际指的是同一领域。这就是为什么在实践中使用类似于您的示例的代码没有多大意义。

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



 类似资料:
  • 问题内容: 我正在准备进行Java认证测试,并且发现了一个与Java静态块的执行有关的有趣问题。我已经花了很多时间阅读有关此主题的内容,但是找不到所需的答案。 我知道将类加载到JVM或调用main方法时会执行静态块,但是… 输出为: 如果我在中包含详细输出,则输出为: 我们可以在这里看到 Child类已加载 到JVM中。 有人可以解释 为什么类的静态块没有执行吗? 问题答案: 您看到该类已加载,但

  • 我已经编写了以下代码,并为这个超类创建了对象。 当我检查输出时,如下所示: 我知道只有在初始化类的对象或进行任何静态引用时,才会执行静态块。但在这里,我并没有把这些都带到课堂上。那么为什么我会看到“sub”即sub类的静态块输出?

  • 这是我的代码: 还有我的测试,我单独运行。 当我运行test foo时,我将看到: 但是当我运行测试栏时,我看到的是: 引用本页内容。。 类对象由Java虚拟机在加载类时自动构造,并通过调用类加载器中的defineClass方法来构造。 所以我的理解是,在测试条中,愚蠢的类被加载,否则我会看到一个空的,我猜?所以类对象被创建,因为类本身被加载。。 现在引用这一页 静态初始化块在JVM(类加载器-具

  • 问题内容: 我正在查看Java代码,并注意到它使用了静态嵌套类。 使用静态嵌套类而不是普通内部类的原因是什么? 我能想到的唯一原因是Entry不能访问实例变量,因此从OOP的角度来看,它具有更好的封装性。 但是我认为可能还有其他原因,也许是性能。可能是什么? 注意。我希望我的术语正确,可以将其称为静态内部类,但是我认为这是错误的:http : //java.sun.com/docs/books/t

  • 问题内容: 为什么不能修饰静态方法或类方法? 双方并导致。 为什么依赖属性而不是属性?(Afaik的所有函数(包括类方法和静态方法)都具有该属性。) 编辑:我正在使用Python 2.6。 问题答案: 当和是最高的装饰器时,它起作用:

  • 问题内容: 当静态方法在子类中被重写时,我对它的行为感到困惑。 下面是代码: 为什么在第二种情况下在这里调用超类的静态方法? 如果方法不是静态的,则根据多态性,当在运行时传递子类对象时,将调用子类的方法。 问题答案: 静态方法的解析始终基于类型。 代码 编译后转换为此 对此,它是对方法的调用而不是对子类方法的调用。因此,您将获得方法的输出。