当前位置: 首页 > 知识库问答 >
问题:

为什么呢。类不调用类中的静态块?

元景天
2023-03-14

这是我的代码:

public class StupidClass {
    static {
        System.out.println("Stupid class loaded!");
    }
}

还有我的测试,我单独运行。

import org.junit.Test;

public class StupidTest {
    @Test
    public void foo() throws ClassNotFoundException {
        final Class<?> stupidClass = Class.forName("StupidClass");
        System.out.println(stupidClass.getSimpleName());
    }

    @Test
    public void bar() throws ClassNotFoundException {
        final Class<StupidClass> stupidClassClass = StupidClass.class;
        System.out.println(stupidClassClass.getSimpleName());
    }
}

当我运行test foo时,我将看到:

Stupid class loaded!
StupidClass

但是当我运行测试栏时,我看到的是:

StupidClass

引用本页内容。。

类对象由Java虚拟机在加载类时自动构造,并通过调用类加载器中的defineClass方法来构造。

所以我的理解是,在测试条中,愚蠢的类被加载,否则我会看到一个空的,我猜?所以类对象被创建,因为类本身被加载。。

现在引用这一页

静态初始化块在JVM(类加载器-具体来说)加载StaticClass(在代码中第一次引用它时发生)时运行。

所以我希望看到“愚蠢的类加载!”测试栏中的文本也是,但我不是。

还引用了Java

Candy、Gum和Cookie类中的每个类都有一个静态子句,该子句在第一次加载该类时执行。

这似乎不太准确。。

我错过了什么?

共有2个答案

秦联
2023-03-14

类加载和初始化是两码事。类可以加载,但在真正必要之前不能初始化。静态初始化器仅在初始化类时运行

在第一种情况下,当您使用class.forName()时,您正在加载和初始化一个类,这就是为什么运行静态初始化器,因此您会看到"愚蠢的类加载!"作为输出。在第二种情况下,您只是分配了一个类的引用,该类已经加载(使用java-详细信息:类来查看加载了什么类),但是您并没有真正初始化它(或者更准确地说,没有做任何强制初始化器运行的事情)。因此,您不会看到输出为加载的愚蠢类!.试着在类上调用newInstance(),它应该强制类的初始化,你应该看到愚蠢的类加载

我的代码:

public class CheckPalindrome {

    public static void main(String[] args) {
        Class<Test> t = Test.class;
    }

}
// class being loaded
class Test {
    static {
        System.out.println("aaa");
    }
}

加载的类

...
[Loaded Test from file:/Workspaces/SampleTest/Java8/bin/]
...

^-这表明类已加载但未初始化。

华锦程
2023-03-14

静态初始化块在JVM(类加载器-具体来说)加载StaticClass(在代码中第一次引用它时发生)时运行。

上面的引语显然是错误的,但这只是一个非常普遍的误解的一个例子。

>

  • 类在加载时不会初始化,而是在第一次引用静态类成员时初始化。这正是由规范控制的。

    类加载不会在第一次引用该类时发生,而是在依赖于实现的点上发生。

    必须加载类的最后时刻是引用该类时,这与引用类成员不同。

    Class.forName默认情况下初始化类,但是您可以选择调用重载,该重载需要布尔初始化并提供false。无需初始化即可加载类。

  •  类似资料:
    • 据我所知,通常应该使用类的引用来调用静态方法,或者如果它位于静态方法或静态块中,则可以不引用直接调用它。 但当从子类静态块调用静态方法时,这是否适用? 为什么它允许这样的事情,因为静态方法不是继承的,所以应该只允许使用父类名对吗? 为什么我的子类静态块可以在没有引用或类名的情况下调用父类静态方法?

    • 问题内容: 为什么不能在Java中将类声明为静态类? 问题答案: 只有嵌套的类可以是静态的。这样,你可以使用嵌套类而无需外部类的实例。

    • 问题内容: 给定以下类别: 我的目标不是像“因为在JLS中这样指定”这样的答案。我知道是的,因为JLS是12.4.1发生初始化时,其读取内容仅为: 类或接口类型T将在以下任何一种首次出现之前立即初始化: … T是一个类,并调用T声明的静态方法。 … 我对没有这样的句子是否有充分的理由感兴趣: T是S的子类,并且在T上调用S声明的静态方法。 问题答案: 我认为这与jvm规范的这一部分有关: 每个框架

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

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

    • 问题内容: 在Java中,外部类可以是public,final,default或abstract。为什么不像静态 问题答案: 外部类已经是隐式静态的。 非静态嵌套类(=内部类)意味着内部类隐式对其父类具有引用。 这就是为什么对于嵌套类,您可以区分静态和非静态。对于外部类来说,这是没有意义的。 这是一个了解静态/非静态嵌套类之间的区别的示例。您应该了解为什么在外部类中它没有意义。